{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Title: #Insert into a Sorted Circular Linked List"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Difficulty: #Medium"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Category Title: #Algorithms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tag Slug: #linked-list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Name Translated: #链表"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solution Name: insert"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Title: #循环有序列表的插入"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Content:\n",
    "<p>给定<strong>循环单调非递减列表</strong>中的一个点，写一个函数向这个列表中插入一个新元素&nbsp;<code>insertVal</code> ，使这个列表仍然是循环非降序的。</p>\n",
    "\n",
    "<p>给定的可以是这个列表中任意一个顶点的指针，并不一定是这个列表中最小元素的指针。</p>\n",
    "\n",
    "<p>如果有多个满足条件的插入位置，你可以选择任意一个位置插入新的值，插入后整个列表仍然保持有序。</p>\n",
    "\n",
    "<p>如果列表为空（给定的节点是 <code>null</code>），你需要创建一个循环有序列表并返回这个节点。否则，请返回原先给定的节点。</p>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>示例 1：</strong></p>\n",
    "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2019/01/19/example_1_before_65p.jpg\" style=\"height: 149px; width: 250px;\" /><br />\n",
    "&nbsp;\n",
    "<pre>\n",
    "<strong>输入：</strong>head = [3,4,1], insertVal = 2\n",
    "<strong>输出：</strong>[3,4,1,2]\n",
    "<strong>解释：</strong>在上图中，有一个包含三个元素的循环有序列表，你获得值为 3 的节点的指针，我们需要向表中插入元素 2 。新插入的节点应该在 1 和 3 之间，插入之后，整个列表如上图所示，最后返回节点 3 。\n",
    "\n",
    "<img alt=\"\" src=\"https://assets.leetcode.com/uploads/2019/01/19/example_1_after_65p.jpg\" style=\"height: 149px; width: 250px;\" />\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 2：</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入：</strong>head = [], insertVal = 1\n",
    "<strong>输出：</strong>[1]\n",
    "<strong>解释：</strong>列表为空（给定的节点是 <code>null</code>），创建一个循环有序列表并返回这个节点。\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 3：</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入：</strong>head = [1], insertVal = 0\n",
    "<strong>输出：</strong>[1,0]\n",
    "</pre>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>提示：</strong></p>\n",
    "\n",
    "<ul>\n",
    "\t<li><code>0 &lt;= Number of Nodes &lt;= 5 * 10<sup>4</sup></code></li>\n",
    "\t<li><code>-10<sup>6</sup> &lt;= Node.val, insertVal &lt;= 10<sup>6</sup></code></li>\n",
    "</ul>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Description: [insert-into-a-sorted-circular-linked-list](https://leetcode.cn/problems/insert-into-a-sorted-circular-linked-list/description/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solutions: [insert-into-a-sorted-circular-linked-list](https://leetcode.cn/problems/insert-into-a-sorted-circular-linked-list/solutions/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_cases = ['[3,4,1]\\n2', '[]\\n1', '[1]\\n0']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def addNegabinary(self, arr1: List[int], arr2: List[int]) -> List[int]:\n",
    "        arr1_index = len(arr1)-1\n",
    "        cur_1 = 0\n",
    "        for i in arr1:\n",
    "            cur_1+= pow(-2,arr1_index)*i\n",
    "            arr1_index-=1\n",
    "        arr2_index = len(arr2)-1\n",
    "        cur_2 = 0\n",
    "        for i in arr2:\n",
    "            cur_2+=pow(-2, arr2_index)*i\n",
    "            arr2_index-=1\n",
    "        cur_1+=cur_2\n",
    "        if cur_1 == 0:return [0]\n",
    "        res = self.to_negative_base(cur_1)\n",
    "        return res\n",
    "    def to_negative_base(self,decimal):\n",
    "        if decimal == 0:\n",
    "            return [0]\n",
    "        \n",
    "        digits = []\n",
    "        while decimal != 0:\n",
    "            remainder = abs(decimal) % 2\n",
    "            digits.insert(0, remainder)\n",
    "            decimal = (decimal - remainder) // -2\n",
    "        \n",
    "        return digits"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict\n",
    "from bisect import bisect_left\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        cnt = defaultdict(list)\n",
    "        res = set()\n",
    "        n = len(keyName)\n",
    "        for i in range(n):\n",
    "            name,time = keyName[i],keyTime[i]\n",
    "            if name in res:\n",
    "                continue\n",
    "            t = self.tomin(time)\n",
    "            idx = bisect_left(cnt[name], t)\n",
    "            cnt[name].insert(idx, t)\n",
    "            if len(cnt[name])-idx>=3:\n",
    "                if cnt[name][idx+2] - t<=60:\n",
    "                    res.add(name)\n",
    "            if idx>=2:\n",
    "                if t - cnt[name][idx-2]<=60:\n",
    "                    res.add(name)\n",
    "            if idx>=1 and idx<len(cnt[name])-1:\n",
    "                if cnt[name][idx+1]-cnt[name][idx-1]<=60:\n",
    "                    res.add(name)\n",
    "            pass\n",
    "        res = list(res)\n",
    "        res.sort()\n",
    "        return res\n",
    "\n",
    "    def tomin(self, text:str):\n",
    "        return int(text[:2])*60 + int(text[3:])\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def __binary_insert(self, arr, item):\n",
    "        if not arr:\n",
    "            arr.append(item)\n",
    "            return\n",
    "\n",
    "        left, right = 0, len(arr) - 1\n",
    "\n",
    "        while left <= right:\n",
    "            mid = (left + right) // 2\n",
    "            curr = arr[mid]\n",
    "\n",
    "            if curr > item:\n",
    "                right = mid - 1\n",
    "            elif curr <= item:\n",
    "                left = mid + 1\n",
    "                \n",
    "        arr.insert(left, item)\n",
    "\n",
    "\n",
    "    def __isIn1Hour(self, timeA, timeB):\n",
    "        hour_diff = int(timeB[0: 2]) - int(timeA[0: 2])\n",
    "        minute_diff = int(timeB[3: 5]) - int(timeA[3: 5])\n",
    "\n",
    "        if  hour_diff == 0:\n",
    "            return True\n",
    "\n",
    "        if hour_diff >= 2:\n",
    "            return False\n",
    "\n",
    "        return minute_diff <= 0\n",
    "\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        record = {}\n",
    "        n = len(keyName)\n",
    "        max_allowed_times = 3\n",
    "        unique_names = []\n",
    "\n",
    "        sorted_records = sorted(zip(keyName, keyTime), key=lambda x: x[1])\n",
    "\n",
    "        for i in range(n):\n",
    "            name, time = sorted_records[i]\n",
    "\n",
    "            lastRecord = record.get(name)\n",
    "\n",
    "            if not lastRecord:\n",
    "                record[name] = (time, time, 1)\n",
    "                continue\n",
    "            \n",
    "            startTime, lastTime, counter = lastRecord\n",
    "            if counter == max_allowed_times:\n",
    "                continue\n",
    "\n",
    "            if self.__isIn1Hour(startTime, time):\n",
    "                if counter == max_allowed_times - 1:\n",
    "                    self.__binary_insert(unique_names, name)\n",
    "                    record[name] = (startTime, time, max_allowed_times)\n",
    "                else:\n",
    "                    record[name] = (startTime, time, counter + 1)\n",
    "            else:\n",
    "                if self.__isIn1Hour(lastTime, time):\n",
    "                    record[name] = (lastTime, time, 2)\n",
    "                else:\n",
    "                    record[name] = (time, time, 1)\n",
    "                \n",
    "\n",
    "        return unique_names\n",
    "                \n",
    "            \n",
    "            \n",
    "            \n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def __binary_insert(self, arr, item):\n",
    "        if not arr:\n",
    "            arr.append(item)\n",
    "            return\n",
    "\n",
    "        left, right = 0, len(arr) - 1\n",
    "\n",
    "        while left <= right:\n",
    "            mid = (left + right) // 2\n",
    "            curr = arr[mid]\n",
    "\n",
    "            if curr > item:\n",
    "                right = mid - 1\n",
    "            elif curr <= item:\n",
    "                left = mid + 1\n",
    "                \n",
    "        arr.insert(left, item)\n",
    "\n",
    "\n",
    "    def __isIn1Hour(self, timeA, timeB):\n",
    "        hour_diff = int(timeB[0: 2]) - int(timeA[0: 2])\n",
    "        minute_diff = int(timeB[3: 5]) - int(timeA[3: 5])\n",
    "\n",
    "        if  hour_diff == 0:\n",
    "            return True\n",
    "\n",
    "        if hour_diff >= 2:\n",
    "            return False\n",
    "\n",
    "        return minute_diff <= 0\n",
    "\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        record = {}\n",
    "        n = len(keyName)\n",
    "        max_allowed_times = 3\n",
    "        unique_names = []\n",
    "\n",
    "        sorted_records = sorted(zip(keyName, keyTime), key=lambda x: x[1])\n",
    "        print(sorted_records)\n",
    "\n",
    "        for i in range(n):\n",
    "            name, time = sorted_records[i]\n",
    "\n",
    "            lastRecord = record.get(name)\n",
    "\n",
    "            if not lastRecord:\n",
    "                record[name] = (time, time, 1)\n",
    "                continue\n",
    "            \n",
    "            startTime, lastTime, counter = lastRecord\n",
    "            if counter == max_allowed_times:\n",
    "                continue\n",
    "\n",
    "            if self.__isIn1Hour(startTime, time):\n",
    "                if counter == max_allowed_times - 1:\n",
    "                    self.__binary_insert(unique_names, name)\n",
    "                    record[name] = (startTime, time, max_allowed_times)\n",
    "                else:\n",
    "                    record[name] = (startTime, time, counter + 1)\n",
    "            else:\n",
    "                if self.__isIn1Hour(lastTime, time):\n",
    "                    record[name] = (lastTime, time, 2)\n",
    "                else:\n",
    "                    record[name] = (time, time, 1)\n",
    "                \n",
    "\n",
    "        return unique_names\n",
    "                \n",
    "            \n",
    "            \n",
    "            \n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Graph: \n",
    "    def __init__(self,vertices): \n",
    "        self.graph = defaultdict(list) \n",
    "        self.V = vertices\n",
    "  \n",
    "    def addEdge(self,u,v): \n",
    "        self.graph[u].append(v) \n",
    "  \n",
    "    def topologicalSortUtil(self,v,visited,stack): \n",
    "  \n",
    "        visited[v] = True\n",
    "  \n",
    "        for i in self.graph[v]: \n",
    "            if visited[i] == False: \n",
    "                self.topologicalSortUtil(i,visited,stack) \n",
    "  \n",
    "        stack.insert(0,v) \n",
    "  \n",
    "    def topologicalSort(self): \n",
    "        visited = [False]*self.V \n",
    "        stack =[] \n",
    "  \n",
    "        for i in range(self.V): \n",
    "            if visited[i] == False: \n",
    "                self.topologicalSortUtil(i,visited,stack)\n",
    "        return stack\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def getAncestors(self, n: int, edges: List[List[int]]) -> List[List[int]]:\n",
    "        father = defaultdict(set)\n",
    "        g = Graph(n)\n",
    "        for _from,_to in edges:\n",
    "            g.addEdge(_from,_to)\n",
    "            father[_to].add(_from)\n",
    "        res = defaultdict(list)\n",
    "        num = g.topologicalSort()\n",
    "        for i in num:\n",
    "            tmp = father[i].copy()\n",
    "            for j in tmp:\n",
    "                father[i] |= father[j]\n",
    "           \n",
    "            res[i]=sorted(list(father[i]))\n",
    "        ans = []\n",
    "        for i in range(n):\n",
    "            ans.append(res[i])\n",
    "        return ans\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class BiNode:\n",
    "    def __init__(self, key='', c=0):\n",
    "        self.c = c\n",
    "        self.keys = [key]\n",
    "        self.prev = None\n",
    "        self.next = None\n",
    "    def insert(self, next):\n",
    "        next.next = self.next\n",
    "        next.prev = self\n",
    "        self.next = next\n",
    "        if next.next:\n",
    "            next.next.prev = next\n",
    "        return next\n",
    "    def remove(self):\n",
    "        prev = self.prev\n",
    "        next = self.next\n",
    "        self.prev = None\n",
    "        self.next = None\n",
    "        if prev:\n",
    "            prev.next = next\n",
    "        if next:\n",
    "            next.prev = prev\n",
    "\n",
    "class AllOne:\n",
    "\n",
    "    def __init__(self):\n",
    "        # 保存key和链表节点对应关系\n",
    "        self.mps = {}\n",
    "        self.head = BiNode()\n",
    "        self.tail = BiNode(c=-1)\n",
    "        self.head.next = self.tail\n",
    "        self.tail.prev = self.head\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.mps:\n",
    "            if self.head.next==self.tail or self.head.next.c>1:\n",
    "                self.mps[key] = self.head.insert(BiNode(key, 1))\n",
    "            else:\n",
    "                self.head.next.keys.append(key)\n",
    "                self.mps[key] = self.head.next\n",
    "        else:\n",
    "            cur = self.mps[key]\n",
    "            if cur.next.c>cur.c+1 or cur.next.c==-1:\n",
    "                self.mps[key] = cur.insert(BiNode(key, cur.c+1))\n",
    "            else:\n",
    "                cur.next.keys.append(key)\n",
    "                self.mps[key] = cur.next\n",
    "            cur.keys.remove(key)\n",
    "            if not cur.keys:\n",
    "                cur.remove()\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        cur = self.mps[key]\n",
    "        if cur.c == 1:\n",
    "            del self.mps[key]\n",
    "        elif cur.prev.c<cur.c-1:\n",
    "            self.mps[key] = cur.prev.insert(BiNode(key, cur.c-1))\n",
    "        else:\n",
    "            cur.prev.keys.append(key)\n",
    "            self.mps[key] = cur.prev\n",
    "        cur.keys.remove(key)\n",
    "        if not cur.keys:\n",
    "            cur.remove()\n",
    "\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        return self.tail.prev.keys[0]\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return self.head.next.keys[0]\n",
    "\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self,count=0,keys=[]):\n",
    "        self.count=count\n",
    "        self.keys=keys\n",
    "        self.prev=None\n",
    "        self.next=None\n",
    "    def insert(self,new_node):\n",
    "        new_node.prev=self\n",
    "        new_node.next=self.next\n",
    "        self.next.prev=new_node\n",
    "        self.next = new_node\n",
    "        return new_node\n",
    "    def remove(self):\n",
    "        self.next.prev=self.prev\n",
    "        self.prev.next=self.next\n",
    "        # The current node is now disconnected from the linked list and can be safely discarded.\n",
    "\n",
    "    \n",
    "class AllOne:\n",
    "    def __init__(self):\n",
    "        self.root=Node()\n",
    "        self.root.next=self.root\n",
    "        self.root.prev=self.root\n",
    "        self.node_map = {}\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        cur = self.node_map.get(key)\n",
    "        if cur:\n",
    "            nxt = cur.next\n",
    "            if nxt.count == cur.count+1:\n",
    "                nxt.keys.append(key)\n",
    "                self.node_map[key] = nxt\n",
    "            else:\n",
    "                self.node_map[key] = cur.insert(Node(cur.count+1,[key]))\n",
    "            cur.keys.remove(key)\n",
    "            if len(cur.keys) ==0:\n",
    "                cur.remove()\n",
    "            \n",
    "        else:\n",
    "            if self.root.next.count==1:\n",
    "                self.root.next.keys.append(key)\n",
    "                self.node_map[key]=self.root.next\n",
    "            else:\n",
    "                self.node_map[key]=self.root.insert(Node(1,[key]))\n",
    "\n",
    "        \n",
    "    def dec(self, key: str) -> None:\n",
    "        cur = self.node_map.get(key)\n",
    "        if cur:\n",
    "            prev=cur.prev\n",
    "            if prev.count==cur.count-1:\n",
    "                prev.keys.append(key)\n",
    "                self.node_map[key]=prev\n",
    "            elif cur.count-1>0:\n",
    "                self.node_map[key] = prev.insert(Node(cur.count-1,[key]))\n",
    "            cur.keys.remove(key)\n",
    "            if len(cur.keys) ==0:\n",
    "                cur.remove()\n",
    "            \n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        return  next(iter(self.root.prev.keys))if self.root.prev != self.root else \"\"\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return  next(iter(self.root.next.keys))if self.root.next != self.root else \"\"\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, cnt: int=0):\n",
    "        self.last = None\n",
    "        self.next = None\n",
    "        self.cnt = cnt\n",
    "        self.keys = set()\n",
    "\n",
    "def insert_node(a: Node, p: Node):\n",
    "    # 在a后面插入b\n",
    "    b = a.next\n",
    "    a.next = p\n",
    "    p.next = b\n",
    "    b.last = p\n",
    "    p.last = a\n",
    "\n",
    "def remove_node(p: Node):\n",
    "    a = p.last\n",
    "    b = p.next\n",
    "    a.next = b\n",
    "    b.last = a\n",
    "    del p\n",
    "\n",
    "class AllOne:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.head = Node()\n",
    "        self.tail = Node()\n",
    "        self.head.next = self.tail\n",
    "        self.tail.last = self.head\n",
    "        self.key_to_node = {}\n",
    "\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.key_to_node:\n",
    "            if self.head.next.cnt == 1:\n",
    "                self.head.next.keys.add(key)\n",
    "                self.key_to_node[key] = self.head.next\n",
    "            else:\n",
    "                node = Node(cnt=1)\n",
    "                node.keys.add(key)\n",
    "                insert_node(self.head, node)\n",
    "                self.key_to_node[key] = node\n",
    "        else:\n",
    "            old_node = self.key_to_node[key]\n",
    "            old_node.keys.remove(key)\n",
    "\n",
    "            cnt = old_node.cnt + 1\n",
    "            if old_node.next.cnt == cnt:\n",
    "                old_node.next.keys.add(key)\n",
    "                self.key_to_node[key] = old_node.next\n",
    "            else:\n",
    "                node = Node(cnt=cnt)\n",
    "                node.keys.add(key)\n",
    "                insert_node(old_node, node)\n",
    "                self.key_to_node[key] = node\n",
    "\n",
    "            if old_node.keys.__len__() == 0:\n",
    "                remove_node(old_node)\n",
    "\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        node = self.key_to_node[key]\n",
    "        cnt = node.cnt - 1\n",
    "        node.keys.remove(key)\n",
    "\n",
    "\n",
    "\n",
    "        if cnt == 0:\n",
    "            self.key_to_node.pop(key)\n",
    "        else:\n",
    "            if node.last.cnt == cnt:\n",
    "                node.last.keys.add(key)\n",
    "                self.key_to_node[key] = node.last\n",
    "            else:\n",
    "                new_node = Node(cnt=cnt)\n",
    "                new_node.keys.add(key)\n",
    "                insert_node(node.last, new_node)\n",
    "                self.key_to_node[key] = new_node\n",
    "\n",
    "        if node.keys.__len__() == 0:\n",
    "            remove_node(node)\n",
    "\n",
    "\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        node = self.tail.last\n",
    "        if node.keys.__len__() == 0:\n",
    "            return \"\"\n",
    "        else:\n",
    "            for key in node.keys:\n",
    "                return key\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        node = self.head.next\n",
    "        if node.keys.__len__() == 0:\n",
    "            return \"\"\n",
    "        else:\n",
    "            for key in node.keys:\n",
    "                return key"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class KeySet:\n",
    "    def __init__(self, key):\n",
    "        self.keys = {key}\n",
    "        self.pre = None\n",
    "        self.next = None\n",
    "    def add_key(self, key):\n",
    "        self.keys.add(key)\n",
    "    def discard_key(self, key):\n",
    "        self.keys.discard(key)\n",
    "    def get_one_key(self):\n",
    "        for key in self.keys:\n",
    "            return key\n",
    "        return None\n",
    "    def remove(self):\n",
    "        self.pre.next = self.next\n",
    "        self.next.pre = self.pre\n",
    "    def insert(self, pre, next):\n",
    "        pre.next = self\n",
    "        self.pre = pre\n",
    "        next.pre = self\n",
    "        self.next = next\n",
    "\n",
    "class AllOne:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.count_keyset = dict()\n",
    "        self.key_count = dict()\n",
    "        self.max_keyset = KeySet('')\n",
    "        self.min_keyset = KeySet('')\n",
    "        self.max_keyset.next = self.min_keyset\n",
    "        self.min_keyset.pre = self.max_keyset\n",
    "        self.count_keyset[0] = self.min_keyset\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        self.key_count[key] = self.key_count.get(key,0)+1\n",
    "        count = self.key_count[key]\n",
    "        if count not in self.count_keyset:\n",
    "            self.count_keyset[count] = KeySet(key)\n",
    "            self.count_keyset[count].insert(self.count_keyset[count-1].pre, self.count_keyset[count-1])\n",
    "        else:\n",
    "            self.count_keyset[count].add_key(key)\n",
    "        self.count_keyset[count-1].discard_key(key)\n",
    "        if self.count_keyset[count-1].get_one_key() is None:\n",
    "            self.count_keyset[count-1].remove()\n",
    "            del self.count_keyset[count-1]\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        self.key_count[key] -= 1\n",
    "        count = self.key_count[key]\n",
    "        if count != 0:\n",
    "            if count not in self.count_keyset:\n",
    "                self.count_keyset[count] = KeySet(key)\n",
    "                self.count_keyset[count].insert(self.count_keyset[count+1], self.count_keyset[count+1].next)\n",
    "            else:\n",
    "                self.count_keyset[count].add_key(key)\n",
    "        self.count_keyset[count+1].discard_key(key)\n",
    "        if self.count_keyset[count+1].get_one_key() is None:\n",
    "            self.count_keyset[count+1].remove()\n",
    "            del self.count_keyset[count+1]\n",
    "        \n",
    "    def getMaxKey(self) -> str:\n",
    "        return self.max_keyset.next.get_one_key()\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return self.min_keyset.pre.get_one_key()\n",
    "\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node():\n",
    "    def __init__(self,key=\"\",count=0):\n",
    "        self.count = count\n",
    "        self.keys = {key}\n",
    "        self.next = None\n",
    "        self.prev = None\n",
    "    def insert(self,node):\n",
    "        node.prev = self\n",
    "        node.next = self.next\n",
    "        node.next.prev = node\n",
    "        node.prev.next = node\n",
    "        return node\n",
    "    def remove(self):\n",
    "        self.prev.next = self.next\n",
    "        self.next.prev = self.prev\n",
    "\n",
    "class AllOne:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "        self.root.prev = self.root\n",
    "        self.root.next = self.root\n",
    "        self.nodes = {}\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.nodes:\n",
    "            if self.root.next is self.root or self.root.next.count > 1:\n",
    "                self.nodes[key] = self.root.insert(Node(key,1))\n",
    "            else:\n",
    "                self.root.next.keys.add(key)\n",
    "                self.nodes[key] = self.root.next\n",
    "        else:\n",
    "            temp = self.nodes[key]\n",
    "            if self.nodes[key].next and self.nodes[key].next.count == self.nodes[key].count+1:\n",
    "                self.nodes[key].next.keys.add(key)\n",
    "                self.nodes[key] = temp.next\n",
    "            else:\n",
    "                self.nodes[key] = temp.insert(Node(key,temp.count+1))\n",
    "            temp.keys.remove(key)\n",
    "            if len(temp.keys) == 0:\n",
    "                temp.remove()\n",
    "    def dec(self, key: str) -> None:\n",
    "        temp = self.nodes[key]\n",
    "        if temp.count == 1:\n",
    "            self.nodes.pop(key)\n",
    "        else:\n",
    "            if temp.prev and temp.prev.count == temp.count - 1:\n",
    "                temp.prev.keys.add(key)\n",
    "                self.nodes[key] = temp.prev\n",
    "            else:\n",
    "                self.nodes[key] = temp.prev.insert(Node(key,temp.count-1))\n",
    "        temp.keys.remove(key)\n",
    "        if len(temp.keys) == 0:\n",
    "                temp.remove()\n",
    "    def getMaxKey(self) -> str:\n",
    "        if self.root != self.root.prev:\n",
    "            return list(self.root.prev.keys)[0]\n",
    "        return \"\"\n",
    "\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        if self.root != self.root.next:\n",
    "            return list(self.root.next.keys)[0]\n",
    "        return \"\"\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class DLNode:\n",
    "    def __init__(self, key, val=set(), prev=None, nex=None):\n",
    "        self._key = key\n",
    "        self._val = val\n",
    "        self._prev = prev\n",
    "        self._nex = nex\n",
    "    \n",
    "    def insert(self, v: str):\n",
    "        self._val.add(v)\n",
    "    \n",
    "    def remove(self, v: str):\n",
    "        self._val.remove(v)\n",
    "    \n",
    "    def isEmpty(self):\n",
    "        return len(self._val) == 0\n",
    "\n",
    "class DLList:\n",
    "    def __init__(self):\n",
    "        self._head = None\n",
    "        self._tail = None\n",
    "    \n",
    "    def insert(self, key, val=set()):\n",
    "        if self._head:\n",
    "            self._head._prev = DLNode(key, val, None, self._head)\n",
    "            self._head = self._head._prev\n",
    "        else:\n",
    "            self._head = self._tail = DLNode(key, val)\n",
    "    \n",
    "    def delete(self, node):\n",
    "        if node._prev != None:\n",
    "            node._prev._nex = node._nex\n",
    "        if node._nex != None:\n",
    "            node._nex._prev = node._prev\n",
    "        \n",
    "        if self._tail == node:\n",
    "            self._tail = node._prev\n",
    "        if self._head == node:\n",
    "            self._head = node._nex\n",
    "\n",
    "    def inc(self, prevNode: Optional[DLNode], val: str) -> DLNode:\n",
    "        wasTail = prevNode == self._tail\n",
    "        wasHead = prevNode == self._head\n",
    "        if prevNode:\n",
    "            prevNode.remove(val)\n",
    "            if prevNode.isEmpty():\n",
    "                self.delete(prevNode)\n",
    "        else:\n",
    "            if self._tail and self._tail._key == 1:\n",
    "                self._tail.insert(val)\n",
    "                return self._tail\n",
    "            newNode = DLNode(1, {val}, self._tail)\n",
    "            if not self._tail:\n",
    "                self._head = self._tail = newNode\n",
    "            else:\n",
    "                self._tail._nex = newNode\n",
    "                self._tail = newNode\n",
    "            return newNode\n",
    "        if prevNode._prev == None:\n",
    "            self.insert(prevNode._key + 1, {val})\n",
    "            return self._head\n",
    "        else:\n",
    "            if prevNode._prev._key != prevNode._key + 1:\n",
    "                newNode = DLNode(prevNode._key + 1, {val}, prevNode._prev)\n",
    "                prevNode._prev._nex = newNode\n",
    "                nexNode = prevNode._nex if prevNode.isEmpty() else prevNode\n",
    "                if nexNode:\n",
    "                    nexNode._prev = newNode\n",
    "                    newNode._nex = nexNode\n",
    "                if wasTail:\n",
    "                    self._tail = newNode\n",
    "                return newNode\n",
    "            else:\n",
    "                prevNode._prev.insert(val)\n",
    "                return prevNode._prev\n",
    "    \n",
    "    def dec(self, prevNode: Optional[DLNode], val: str) -> Optional[DLNode]:\n",
    "        prevNode.remove(val)\n",
    "        wasHead = self._head == prevNode\n",
    "        wasTail = self._tail == prevNode\n",
    "        if prevNode.isEmpty():\n",
    "            self.delete(prevNode)\n",
    "        newKey = prevNode._key - 1\n",
    "        if newKey == 0:\n",
    "            return None\n",
    "        if prevNode._nex == None or prevNode._nex._key != newKey:\n",
    "            prev = prevNode._prev if prevNode.isEmpty() else prevNode\n",
    "            newNode = DLNode(newKey, {val}, prev, prevNode._nex)\n",
    "            if prev:\n",
    "                prev._nex = newNode\n",
    "            if prevNode._nex:\n",
    "                prevNode._nex._prev = newNode\n",
    "            if wasTail:\n",
    "                self._tail = newNode\n",
    "            if wasHead and prevNode.isEmpty():\n",
    "                self._head = newNode\n",
    "            return newNode\n",
    "        else:\n",
    "            prevNode._nex.insert(val)\n",
    "            return prevNode._nex\n",
    "\n",
    "class AllOne:\n",
    "\n",
    "    def __init__(self):\n",
    "        self._strToNode = defaultdict(DLNode)\n",
    "        self._dl = DLList()\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        prevNode = self._strToNode[key] if key in self._strToNode else None\n",
    "        self._strToNode[key] = self._dl.inc(prevNode, key)\n",
    "        # print(self._dl._head._key, self._dl._head._val)\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        prevNode = self._strToNode[key]\n",
    "        self._strToNode[key] = self._dl.dec(prevNode, key)\n",
    "        # print(self._dl._tail._key, self._dl._tail._val)\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        return next(iter(self._dl._head._val)) if self._dl._head else \"\"\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return next(iter(self._dl._tail._val)) if self._dl._tail else \"\"\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class KeySet:\n",
    "    def __init__(self, key):\n",
    "        self.keys = {key}\n",
    "        self.pre = None\n",
    "        self.next = None\n",
    "    def len(self):\n",
    "        return len(self.keys)\n",
    "    def add_key(self, key):\n",
    "        self.keys.add(key)\n",
    "    def discard_key(self, key):\n",
    "        self.keys.discard(key)\n",
    "    def get_one_key(self):\n",
    "        for key in self.keys:\n",
    "            return key\n",
    "    def remove(self):\n",
    "        self.pre.next = self.next\n",
    "        self.next.pre = self.pre\n",
    "    def insert(self, pre, next):\n",
    "        pre.next = self\n",
    "        self.pre = pre\n",
    "        next.pre = self\n",
    "        self.next = next\n",
    "\n",
    "class AllOne:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.count_keyset = dict()\n",
    "        self.key_count = dict()\n",
    "        self.max_keyset = KeySet('')\n",
    "        self.min_keyset = KeySet('')\n",
    "        self.max_keyset.next = self.min_keyset\n",
    "        self.min_keyset.pre = self.max_keyset\n",
    "        self.count_keyset[0] = self.min_keyset\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        self.key_count[key] = self.key_count.get(key,0)+1\n",
    "        count = self.key_count[key]\n",
    "        if count not in self.count_keyset:\n",
    "            self.count_keyset[count] = KeySet(key)\n",
    "            self.count_keyset[count].insert(self.count_keyset[count-1].pre, self.count_keyset[count-1])\n",
    "        else:\n",
    "            self.count_keyset[count].add_key(key)\n",
    "        self.count_keyset[count-1].discard_key(key)\n",
    "        if self.count_keyset[count-1].len() == 0:\n",
    "            self.count_keyset[count-1].remove()\n",
    "            del self.count_keyset[count-1]\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        self.key_count[key] -= 1\n",
    "        count = self.key_count[key]\n",
    "        if count != 0:\n",
    "            if count not in self.count_keyset:\n",
    "                self.count_keyset[count] = KeySet(key)\n",
    "                self.count_keyset[count].insert(self.count_keyset[count+1], self.count_keyset[count+1].next)\n",
    "            else:\n",
    "                self.count_keyset[count].add_key(key)\n",
    "        self.count_keyset[count+1].discard_key(key)\n",
    "        if self.count_keyset[count+1].len() == 0:\n",
    "            self.count_keyset[count+1].remove()\n",
    "            del self.count_keyset[count+1]\n",
    "        \n",
    "    def getMaxKey(self) -> str:\n",
    "        return self.max_keyset.next.get_one_key()\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return self.min_keyset.pre.get_one_key()\n",
    "\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, key=\"\",count=0):\n",
    "        self.prev = None\n",
    "        self.next = None\n",
    "        self.keys = {key}\n",
    "        self.count = count\n",
    "    def insert(self, node: 'Node')->'Node':\n",
    "        node.prev = self\n",
    "        node.next = self.next\n",
    "        node.prev.next = node\n",
    "        node.next.prev = node\n",
    "        return node\n",
    "    def remove(self):\n",
    "        self.prev.next = self.next\n",
    "        self.next.prev = self.prev\n",
    "\n",
    "class AllOne:\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "        self.root.prev = self.root\n",
    "        self.root.next = self.root\n",
    "        self.nodes = {} # dict\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.nodes:\n",
    "            if self.root.next is self.root or self.root.next.count > 1:\n",
    "                self.nodes[key] = self.root.insert(Node(key,1))\n",
    "            else:\n",
    "                self.root.next.keys.add(key)\n",
    "                self.nodes[key]=self.root.next\n",
    "        else:\n",
    "            cur = self.nodes[key]\n",
    "            nxt = cur.next\n",
    "            if nxt is self.root or nxt.count>cur.count+1:\n",
    "                self.nodes[key]=cur.insert(Node(key,cur.count+1))\n",
    "            else:\n",
    "                nxt.keys.add(key)\n",
    "                self.nodes[key]=nxt\n",
    "            cur.keys.remove(key)\n",
    "            if len(cur.keys)==0:\n",
    "                cur.remove()\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        cur = self.nodes[key]\n",
    "        if cur.count==1:\n",
    "            del self.nodes[key]\n",
    "        else: \n",
    "            pre = cur.prev\n",
    "            if pre==self.root or pre.count<cur.count-1:\n",
    "                self.nodes[key] = cur.prev.insert(Node(key,cur.count-1))\n",
    "            else:\n",
    "                pre.keys.add(key)\n",
    "                self.nodes[key] = pre\n",
    "        cur.keys.remove(key)\n",
    "        if len(cur.keys)==0:\n",
    "            cur.remove()\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        if self.root.prev is not self.root:\n",
    "            return next(iter(self.root.prev.keys))\n",
    "        else:\n",
    "            return \"\"\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        if self.root.next is not self.root:\n",
    "            return next(iter(self.root.next.keys))\n",
    "        else:\n",
    "            return \"\"\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, key=\"\", count=0):\n",
    "        self.prev = None\n",
    "        self.next = None\n",
    "        self.keys = {key}\n",
    "        self.count = count\n",
    "\n",
    "    def insert(self, node: 'Node') -> 'Node':  # 在 self 后插入 node\n",
    "        node.prev = self\n",
    "        node.next = self.next\n",
    "        node.prev.next = node\n",
    "        node.next.prev = node\n",
    "        return node\n",
    "\n",
    "    def remove(self):  # 从链表中移除 self\n",
    "        self.prev.next = self.next\n",
    "        self.next.prev = self.prev\n",
    "\n",
    "class AllOne:\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "        self.root.prev = self.root\n",
    "        self.root.next = self.root  # 初始化链表哨兵，下面判断节点的 next 若为 self.root，则表示 next 为空（prev 同理）\n",
    "        self.nodes = {}\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.nodes:  # key 不在链表中\n",
    "            if self.root.next is self.root or self.root.next.count > 1:\n",
    "                self.nodes[key] = self.root.insert(Node(key, 1))\n",
    "            else:\n",
    "                self.root.next.keys.add(key)\n",
    "                self.nodes[key] = self.root.next\n",
    "        else:\n",
    "            cur = self.nodes[key]\n",
    "            nxt = cur.next\n",
    "            if nxt is self.root or nxt.count > cur.count + 1:\n",
    "                self.nodes[key] = cur.insert(Node(key, cur.count + 1))\n",
    "            else:\n",
    "                nxt.keys.add(key)\n",
    "                self.nodes[key] = nxt\n",
    "            cur.keys.remove(key)\n",
    "            if len(cur.keys) == 0:\n",
    "                cur.remove()\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        cur = self.nodes[key]\n",
    "        if cur.count == 1:  # key 仅出现一次，将其移出 nodes\n",
    "            del self.nodes[key]\n",
    "        else:\n",
    "            pre = cur.prev\n",
    "            if pre is self.root or pre.count < cur.count - 1:\n",
    "                self.nodes[key] = cur.prev.insert(Node(key, cur.count - 1))\n",
    "            else:\n",
    "                pre.keys.add(key)\n",
    "                self.nodes[key] = pre\n",
    "        cur.keys.remove(key)\n",
    "        if len(cur.keys) == 0:\n",
    "            cur.remove()\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        return next(iter(self.root.prev.keys)) if self.root.prev is not self.root else \"\"\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return next(iter(self.root.next.keys)) if self.root.next is not self.root else \"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Bucket:\n",
    "    def __init__(self,s,c):\n",
    "        self.set = set()\n",
    "        self.set.add(s)\n",
    "        self.cnt = c\n",
    "        self.last = None\n",
    "        self.next = None\n",
    "class AllOne:\n",
    "    def __init__(self):\n",
    "        self.head = Bucket(\"\",0)\n",
    "        self.tail = Bucket(\"\",float('inf'))\n",
    "        self.head.next = self.tail\n",
    "        self.tail.last = self.head\n",
    "        self.map = dict()\n",
    "    def insert(self,cur,pos):\n",
    "        cur.next.last = pos\n",
    "        pos.next = cur.next\n",
    "        cur.next = pos\n",
    "        pos.last = cur\n",
    "    def remove(self,cur):\n",
    "        cur.last.next = cur.next\n",
    "        cur.next.last = cur.last\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.map:\n",
    "            if self.head.next.cnt == 1:\n",
    "                self.map[key] = self.head.next\n",
    "                self.head.next.set.add(key)\n",
    "            else:\n",
    "                newBucket = Bucket(key,1)\n",
    "                self.map[key] = newBucket\n",
    "                self.insert(self.head,newBucket)\n",
    "        else:\n",
    "            bucket = self.map.get(key)\n",
    "            if bucket.next.cnt == bucket.cnt+1:\n",
    "                self.map[key] = bucket.next\n",
    "                bucket.next.set.add(key)\n",
    "            else:\n",
    "                newBucket = Bucket(key,bucket.cnt+1)\n",
    "                self.map[key] = newBucket\n",
    "                self.insert(bucket,newBucket)\n",
    "            bucket.set.remove(key)\n",
    "            if len(bucket.set) == 0:\n",
    "                self.remove(bucket)\n",
    "    def dec(self, key: str) -> None:\n",
    "        bucket = self.map.get(key)\n",
    "        if bucket.cnt == 1:\n",
    "            del self.map[key]\n",
    "        else:\n",
    "            if bucket.last.cnt == bucket.cnt-1:\n",
    "                self.map[key] = bucket.last\n",
    "                bucket.last.set.add(key)\n",
    "            else:\n",
    "                newBucket = Bucket(key,bucket.cnt-1)\n",
    "                self.map[key] = newBucket\n",
    "                self.insert(bucket.last,newBucket)\n",
    "        bucket.set.remove(key)\n",
    "        if len(bucket.set)==0:\n",
    "            self.remove(bucket)\n",
    "    def getMaxKey(self) -> str:\n",
    "        return next(iter(self.tail.last.set))\n",
    "    def getMinKey(self) -> str:\n",
    "        return next(iter(self.head.next.set))\n",
    "\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, key=\"\", count=0):\n",
    "        self.prev = None\n",
    "        self.next = None\n",
    "        self.keys = {key}\n",
    "        self.count = count\n",
    "\n",
    "    def insert(self, node: 'Node') -> 'Node':  # 在 self 后插入 node\n",
    "        node.prev = self\n",
    "        node.next = self.next\n",
    "        node.prev.next = node\n",
    "        node.next.prev = node\n",
    "        return node\n",
    "\n",
    "    def remove(self):  # 从链表中移除 self\n",
    "        self.prev.next = self.next\n",
    "        self.next.prev = self.prev\n",
    "\n",
    "class AllOne:\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "        self.root.prev = self.root\n",
    "        self.root.next = self.root  # 初始化链表哨兵，下面判断节点的 next 若为 self.root，则表示 next 为空（prev 同理）\n",
    "        self.nodes = {}\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.nodes:  # key 不在链表中\n",
    "            if self.root.next is self.root or self.root.next.count > 1:\n",
    "                self.nodes[key] = self.root.insert(Node(key, 1))\n",
    "            else:\n",
    "                self.root.next.keys.add(key)\n",
    "                self.nodes[key] = self.root.next\n",
    "        else:\n",
    "            cur = self.nodes[key]\n",
    "            nxt = cur.next\n",
    "            if nxt is self.root or nxt.count > cur.count + 1:\n",
    "                self.nodes[key] = cur.insert(Node(key, cur.count + 1))\n",
    "            else:\n",
    "                nxt.keys.add(key)\n",
    "                self.nodes[key] = nxt\n",
    "            cur.keys.remove(key)\n",
    "            if len(cur.keys) == 0:\n",
    "                cur.remove()\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        cur = self.nodes[key]\n",
    "        if cur.count == 1:  # key 仅出现一次，将其移出 nodes\n",
    "            del self.nodes[key]\n",
    "        else:\n",
    "            pre = cur.prev\n",
    "            if pre is self.root or pre.count < cur.count - 1:\n",
    "                self.nodes[key] = cur.prev.insert(Node(key, cur.count - 1))\n",
    "            else:\n",
    "                pre.keys.add(key)\n",
    "                self.nodes[key] = pre\n",
    "        cur.keys.remove(key)\n",
    "        if len(cur.keys) == 0:\n",
    "            cur.remove()\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        return next(iter(self.root.prev.keys)) if self.root.prev is not self.root else \"\"\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return next(iter(self.root.next.keys)) if self.root.next is not self.root else \"\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, key=\"\", count=0):\n",
    "        self.prev = None\n",
    "        self.next = None\n",
    "        self.keys = {key}\n",
    "        self.count = count\n",
    "\n",
    "    def insert(self, node: 'Node') -> 'Node':  # 在 self 后插入 node\n",
    "        node.prev = self\n",
    "        node.next = self.next\n",
    "        node.prev.next = node\n",
    "        node.next.prev = node\n",
    "        return node\n",
    "\n",
    "    def remove(self):  # 从链表中移除 self\n",
    "        self.prev.next = self.next\n",
    "        self.next.prev = self.prev\n",
    "\n",
    "class AllOne:\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "        self.root.prev = self.root\n",
    "        self.root.next = self.root  # 初始化链表哨兵，下面判断节点的 next 若为 self.root，则表示 next 为空（prev 同理）\n",
    "        self.nodes = {}\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.nodes:  # key 不在链表中\n",
    "            if self.root.next is self.root or self.root.next.count > 1:\n",
    "                self.nodes[key] = self.root.insert(Node(key, 1))\n",
    "            else:\n",
    "                self.root.next.keys.add(key)\n",
    "                self.nodes[key] = self.root.next\n",
    "        else:\n",
    "            cur = self.nodes[key]\n",
    "            nxt = cur.next\n",
    "            if nxt is self.root or nxt.count > cur.count + 1:\n",
    "                self.nodes[key] = cur.insert(Node(key, cur.count + 1))\n",
    "            else:\n",
    "                nxt.keys.add(key)\n",
    "                self.nodes[key] = nxt\n",
    "            cur.keys.remove(key)\n",
    "            if len(cur.keys) == 0:\n",
    "                cur.remove()\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        cur = self.nodes[key]\n",
    "        if cur.count == 1:  # key 仅出现一次，将其移出 nodes\n",
    "            del self.nodes[key]\n",
    "        else:\n",
    "            pre = cur.prev\n",
    "            if pre is self.root or pre.count < cur.count - 1:\n",
    "                self.nodes[key] = cur.prev.insert(Node(key, cur.count - 1))\n",
    "            else:\n",
    "                pre.keys.add(key)\n",
    "                self.nodes[key] = pre\n",
    "        cur.keys.remove(key)\n",
    "        if len(cur.keys) == 0:\n",
    "            cur.remove()\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        return next(iter(self.root.prev.keys)) if self.root.prev is not self.root else \"\"\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return next(iter(self.root.next.keys)) if self.root.next is not self.root else \"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# 链表\n",
    "class Node:\n",
    "    def __init__(self, key=\"\", count=0):\n",
    "        self.prev = None\n",
    "        self.next = None\n",
    "        self.keys = {key}\n",
    "        self.count = count\n",
    "\n",
    "    def insert(self, node: 'Node') -> 'Node':  # 在 self 后插入 node\n",
    "        node.prev = self\n",
    "        node.next = self.next\n",
    "        node.prev.next = node\n",
    "        node.next.prev = node\n",
    "        return node\n",
    "\n",
    "    def remove(self):  # 从链表中移除 self\n",
    "        self.prev.next = self.next\n",
    "        self.next.prev = self.prev\n",
    "\n",
    "\n",
    "\n",
    "class AllOne:\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "        self.root.prev = self.root\n",
    "        self.root.next = self.root  # 初始化链表哨兵，下面判断节点的 next 若为 self.root，则表示 next 为空（prev 同理）\n",
    "        self.nodes = {}\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.nodes:  # key 不在链表中\n",
    "            if self.root.next is self.root or self.root.next.count > 1:\n",
    "                self.nodes[key] = self.root.insert(Node(key, 1))\n",
    "            else:\n",
    "                self.root.next.keys.add(key)\n",
    "                self.nodes[key] = self.root.next\n",
    "        else:\n",
    "            cur = self.nodes[key]\n",
    "            nxt = cur.next\n",
    "            if nxt is self.root or nxt.count > cur.count + 1:\n",
    "                self.nodes[key] = cur.insert(Node(key, cur.count + 1))\n",
    "            else:\n",
    "                nxt.keys.add(key)\n",
    "                self.nodes[key] = nxt\n",
    "            cur.keys.remove(key)\n",
    "            if len(cur.keys) == 0:\n",
    "                cur.remove()\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        cur = self.nodes[key]\n",
    "        if cur.count == 1:  # key 仅出现一次，将其移出 nodes\n",
    "            del self.nodes[key]\n",
    "        else:\n",
    "            pre = cur.prev\n",
    "            if pre is self.root or pre.count < cur.count - 1:\n",
    "                self.nodes[key] = cur.prev.insert(Node(key, cur.count - 1))\n",
    "            else:\n",
    "                pre.keys.add(key)\n",
    "                self.nodes[key] = pre\n",
    "        cur.keys.remove(key)\n",
    "        if len(cur.keys) == 0:\n",
    "            cur.remove()\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        # next(iter(set)) 获取 集合的第一个元素\n",
    "        return next(iter(self.root.prev.keys)) if self.root.prev is not self.root else \"\"\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return next(iter(self.root.next.keys)) if self.root.next is not self.root else \"\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Bucket:\n",
    "    def __init__(self,s,c):\n",
    "        self.set = set()\n",
    "        self.set.add(s)\n",
    "        self.cnt = c\n",
    "        self.last = None\n",
    "        self.next = None\n",
    "class AllOne:\n",
    "    def __init__(self):\n",
    "        self.head = Bucket(\"\",0)\n",
    "        self.tail = Bucket(\"\",float('inf'))\n",
    "        self.head.next = self.tail\n",
    "        self.tail.last = self.head\n",
    "        self.map = dict()\n",
    "    def insert(self,cur,pos):\n",
    "        cur.next.last = pos\n",
    "        pos.next = cur.next\n",
    "        cur.next = pos\n",
    "        pos.last = cur\n",
    "    def remove(self,cur):\n",
    "        cur.last.next = cur.next\n",
    "        cur.next.last = cur.last\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.map:\n",
    "            if self.head.next.cnt == 1:\n",
    "                self.map[key] = self.head.next\n",
    "                self.head.next.set.add(key)\n",
    "            else:\n",
    "                newBucket = Bucket(key,1)\n",
    "                self.map[key] = newBucket\n",
    "                self.insert(self.head,newBucket)\n",
    "        else:\n",
    "            bucket = self.map.get(key)\n",
    "            if bucket.next.cnt == bucket.cnt+1:\n",
    "                self.map[key] = bucket.next\n",
    "                bucket.next.set.add(key)\n",
    "            else:\n",
    "                newBucket = Bucket(key,bucket.cnt+1)\n",
    "                self.map[key] = newBucket\n",
    "                self.insert(bucket,newBucket)\n",
    "            bucket.set.remove(key)\n",
    "            if len(bucket.set) == 0:\n",
    "                self.remove(bucket)\n",
    "    def dec(self, key: str) -> None:\n",
    "        bucket = self.map.get(key)\n",
    "        if bucket.cnt == 1:\n",
    "            del self.map[key]\n",
    "        else:\n",
    "            if bucket.last.cnt == bucket.cnt-1:\n",
    "                self.map[key] = bucket.last\n",
    "                bucket.last.set.add(key)\n",
    "            else:\n",
    "                newBucket = Bucket(key,bucket.cnt-1)\n",
    "                self.map[key] = newBucket\n",
    "                self.insert(bucket.last,newBucket)\n",
    "        bucket.set.discard(key)\n",
    "        if len(bucket.set)==0:\n",
    "            self.remove(bucket)\n",
    "    def getMaxKey(self) -> str:\n",
    "        return next(iter(self.tail.last.set))\n",
    "    def getMinKey(self) -> str:\n",
    "        return next(iter(self.head.next.set))\n",
    "\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, key=\"\", count=0):\n",
    "        self.prev = None\n",
    "        self.next = None\n",
    "        self.keys = {key}\n",
    "        self.count = count\n",
    "\n",
    "    def insert(self, node: 'Node') -> 'Node':  # 在 self 后插入 node\n",
    "        node.prev = self\n",
    "        node.next = self.next\n",
    "        node.prev.next = node\n",
    "        node.next.prev = node\n",
    "        return node\n",
    "\n",
    "    def remove(self):  # 从链表中移除 self\n",
    "        self.prev.next = self.next\n",
    "        self.next.prev = self.prev\n",
    "\n",
    "class AllOne:\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "        self.root.prev = self.root\n",
    "        self.root.next = self.root  # 初始化链表哨兵，下面判断节点的 next 若为 self.root，则表示 next 为空（prev 同理）\n",
    "        self.nodes = {}\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key not in self.nodes:  # key 不在链表中\n",
    "            if self.root.next is self.root or self.root.next.count > 1:\n",
    "                self.nodes[key] = self.root.insert(Node(key, 1))\n",
    "            else:\n",
    "                self.root.next.keys.add(key)\n",
    "                self.nodes[key] = self.root.next\n",
    "        else:\n",
    "            cur = self.nodes[key]\n",
    "            nxt = cur.next\n",
    "            if nxt is self.root or nxt.count > cur.count + 1:\n",
    "                self.nodes[key] = cur.insert(Node(key, cur.count + 1))\n",
    "            else:\n",
    "                nxt.keys.add(key)\n",
    "                self.nodes[key] = nxt\n",
    "            cur.keys.remove(key)\n",
    "            if len(cur.keys) == 0:\n",
    "                cur.remove()\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        cur = self.nodes[key]\n",
    "        if cur.count == 1:  # key 仅出现一次，将其移出 nodes\n",
    "            del self.nodes[key]\n",
    "        else:\n",
    "            pre = cur.prev\n",
    "            if pre is self.root or pre.count < cur.count - 1:\n",
    "                self.nodes[key] = cur.prev.insert(Node(key, cur.count - 1))\n",
    "            else:\n",
    "                pre.keys.add(key)\n",
    "                self.nodes[key] = pre\n",
    "        cur.keys.remove(key)\n",
    "        if len(cur.keys) == 0:\n",
    "            cur.remove()\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        return next(iter(self.root.prev.keys)) if self.root.prev is not self.root else \"\"\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        return next(iter(self.root.next.keys)) if self.root.next is not self.root else \"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from sortedcontainers import SortedDict\n",
    "class AllOne:\n",
    "\n",
    "    def __init__(self):\n",
    "        from sortedcontainers import SortedList\n",
    "        self.l1= []\n",
    "        self.l2=SortedList()\n",
    "\n",
    "\n",
    "    def inc(self, key: str) -> None:\n",
    "        if key in self.l1:\n",
    "            x=self.l1.index(key)\n",
    "            y=self.l2[x]+1\n",
    "            self.l1.pop(x)\n",
    "            self.l2.pop(x)\n",
    "            self.l2.add(y)\n",
    "            x1=self.l2.index(y)\n",
    "            self.l1.insert(x1,key)\n",
    "        else:\n",
    "            self.l1.insert(0,key)\n",
    "            self.l2.add(1)\n",
    "\n",
    "\n",
    "\n",
    "    def dec(self, key: str) -> None:\n",
    "        x=self.l1.index(key)\n",
    "        if self.l2[x]==1:\n",
    "            self.l1.pop(x)\n",
    "            self.l2.pop(x)\n",
    "        else:\n",
    "            y = self.l2[x] - 1\n",
    "            self.l1.pop(x)\n",
    "            self.l2.pop(x)\n",
    "            self.l2.add(y)\n",
    "            x1 = self.l2.index(y)\n",
    "            self.l1.insert(x1, key)\n",
    "\n",
    "\n",
    "    def getMaxKey(self) -> str:\n",
    "        if not self.l1:return ''\n",
    "\n",
    "        return self.l1[-1]\n",
    "\n",
    "\n",
    "    def getMinKey(self) -> str:\n",
    "        if not self.l1: return ''\n",
    "        return self.l1[0]\n",
    "\n",
    "\n",
    "\n",
    "# Your AllOne object will be instantiated and called as such:\n",
    "# obj = AllOne()\n",
    "# obj.inc(key)\n",
    "# obj.dec(key)\n",
    "# param_3 = obj.getMaxKey()\n",
    "# param_4 = obj.getMinKey()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def ambiguousCoordinates(self, s: str) -> List[str]:\n",
    "        # s = s[1:-1]  # Removing the brackets\n",
    "\n",
    "        # def isValid(num: str) -> bool:\n",
    "        #     # Check if the number is a valid integer or decimal\n",
    "        #     if len(num) > 1 and num[0] == '0' and '.' not in num:\n",
    "        #         return False\n",
    "        #     if num[-1] == '0' and '.' in num:\n",
    "        #         return False\n",
    "        #     return True\n",
    "\n",
    "        # def generateNumbers(part: str) -> List[str]:\n",
    "        #     # Generate all possible valid numbers by inserting a decimal point\n",
    "        #     n = len(part)\n",
    "        #     if n == 1:\n",
    "        #         return [part]\n",
    "        #     if part[0] == '0':\n",
    "        #         if part[-1] == '0':\n",
    "        #             return []\n",
    "        #         else:\n",
    "        #             return [f\"{part[:1]}.{part[1:]}\"]\n",
    "        #     if part[-1] == '0':\n",
    "        #         return [part]\n",
    "        #     ans = [part]\n",
    "        #     for i in range(1, n):\n",
    "        #         ans.append(f\"{part[:i]}.{part[i:]}\")\n",
    "        #     return [x for x in ans if isValid(x)]\n",
    "        \n",
    "        # ans = []\n",
    "        # for i in range(1, len(s)):\n",
    "        #     left, right = s[:i], s[i:]\n",
    "        #     for l in generateNumbers(left):\n",
    "        #         for r in generateNumbers(right):\n",
    "        #             ans.append(f\"({l}, {r})\")\n",
    "        # return ans\n",
    "        s=s[1:-1]\n",
    "        n=len(s)\n",
    "        ans =[]\n",
    "        def dfs(s,path):\n",
    "            if  not s or len(path)==n:\n",
    "                ans.append(path)\n",
    "            for i in range(len(s)):\n",
    "                dfs(s[i+1:], path+[s[:i+1]])\n",
    "        dfs(s,[])\n",
    "        cache = defaultdict(int)\n",
    "        ans =[\n",
    "            ians\n",
    "            for ians in ans if len(ians)==2\n",
    "\n",
    "        ]\n",
    "        def isValid(num: str) -> bool:\n",
    "            # Check if the number is a valid integer or decimal\n",
    "            if len(num) > 1 and num[0] == '0' and '.' not in num:\n",
    "                return False\n",
    "            if num[-1] == '0' and '.' in num:\n",
    "                return False\n",
    "            return True\n",
    "\n",
    "        def generateNumbers(part: str) -> List[str]:\n",
    "            # Generate all possible valid numbers by inserting a decimal point\n",
    "            n = len(part)\n",
    "            if n == 1:\n",
    "                return [part]\n",
    "            if part[0] == '0':\n",
    "                if part[-1] == '0':\n",
    "                    return []\n",
    "                else:\n",
    "                    return [f\"{part[:1]}.{part[1:]}\"]\n",
    "            if part[-1] == '0':\n",
    "                return [part]\n",
    "            ans = [part]\n",
    "            for i in range(1, n):\n",
    "                ans.append(f\"{part[:i]}.{part[i:]}\")\n",
    "            return [x for x in ans if isValid(x)]\n",
    "\n",
    "        res=[]\n",
    "        \n",
    "        for (k,v) in ans:\n",
    "            for ks in generateNumbers(k):\n",
    "               for  vs in generateNumbers(v):\n",
    "                    res.append(f\"({ks}, {vs})\")\n",
    "\n",
    "         \n",
    "        return res\n",
    "        \n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def numberOfPatterns(self, m: int, n: int) -> int:\n",
    "        iniState = 0\n",
    "        def getRow(state, r):\n",
    "            return (state>>(r*3)) & int('111', 2)\n",
    "        def getCol(state, c):\n",
    "            ret = 0\n",
    "            for r in range(3):\n",
    "                ret<<=1\n",
    "                row = getRow(state, r)\n",
    "                ret += (row>>c)&1\n",
    "            return ret\n",
    "        def validRC(num):\n",
    "            return num != 5\n",
    "        def R(n):\n",
    "            return n//3\n",
    "        def C(n):\n",
    "            return n%3\n",
    "        # def validX(state):\n",
    "        #     if int('100010001', 2) & state == int('100000001', 2): return False\n",
    "        #     if int('001010100', 2) & state == int('001000100', 2): return False\n",
    "        #     return True\n",
    "        def isValidInsert(state, last, new):\n",
    "            last, new = last-1, new-1\n",
    "            if R(last) == R(new) and not validRC(getRow(state, R(last))): return False\n",
    "            if C(last) == C(new) and not validRC(getCol(state, C(last))): return False\n",
    "            if last+new == 8: return (state & int('000010000', 2)) != 0\n",
    "            return True\n",
    "            \n",
    "        def isEmptyPoint(state, new):\n",
    "            return state & (1 << (new-1)) == 0\n",
    "        def insert(state, new):\n",
    "            return state | (1 << (new-1))\n",
    "\n",
    "        # tb = 0\n",
    "        # tb = insert(tb, 1)\n",
    "        # tb = insert(tb, 9)\n",
    "        # print(isValidInsert(tb, 1, 9))\n",
    "        \n",
    "        curStates = collections.deque([(0, -1)])\n",
    "        # print(curStates)\n",
    "        # print(isValidBoard(int('100000001', 2)))\n",
    "        ret = 0\n",
    "        for i in range(1, m):\n",
    "            dqn = len(curStates)\n",
    "            for _ in range(dqn):\n",
    "                iniState, last = curStates.popleft()\n",
    "                for newP in range(1, 10):\n",
    "                    if isEmptyPoint(iniState, newP):\n",
    "                        newState = insert(iniState, newP)\n",
    "                        if last == -1: curStates.append((newState, newP))\n",
    "                        elif isValidInsert(newState, last, newP):\n",
    "                            curStates.append((newState, newP))\n",
    "        # print(curStates)\n",
    "        for i in range(m, n+1):\n",
    "            dqn = len(curStates)\n",
    "            for _ in range(dqn):\n",
    "                iniState, last = curStates.popleft()\n",
    "                for newP in range(1, 10):\n",
    "                    if isEmptyPoint(iniState, newP):\n",
    "                        newState = insert(iniState, newP)\n",
    "                        # print(newState)\n",
    "                        if last == -1: curStates.append((newState, newP))\n",
    "                        elif isValidInsert(newState, last, newP):\n",
    "                            curStates.append((newState, newP))\n",
    "            ret+=len(curStates)\n",
    "        # print(curStates)\n",
    "        return ret\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def numberOfPatterns(self, m: int, n: int) -> int:\n",
    "        iniState = 0\n",
    "        def getRow(state, r):\n",
    "            return (state>>(r*3)) & int('111', 2)\n",
    "        def getCol(state, c):\n",
    "            ret = 0\n",
    "            for r in range(3):\n",
    "                ret<<=1\n",
    "                row = getRow(state, r)\n",
    "                ret += (row>>c)&1\n",
    "            return ret\n",
    "        def validRC(num):\n",
    "            return num != 5\n",
    "        def R(n):\n",
    "            return n//3\n",
    "        def C(n):\n",
    "            return n%3\n",
    "        # def validX(state):\n",
    "        #     if int('100010001', 2) & state == int('100000001', 2): return False\n",
    "        #     if int('001010100', 2) & state == int('001000100', 2): return False\n",
    "        #     return True\n",
    "        def isValidInsert(state, last, new):\n",
    "            last, new = last-1, new-1\n",
    "            if R(last) == R(new) and not validRC(getRow(state, R(last))): return False\n",
    "            if C(last) == C(new) and not validRC(getCol(state, C(last))): return False\n",
    "            if last+new == 8: return (state & int('000010000', 2)) != 0\n",
    "            return True\n",
    "            \n",
    "        def isEmptyPoint(state, new):\n",
    "            return state & (1 << (new-1)) == 0\n",
    "        def insert(state, new):\n",
    "            return state | (1 << (new-1))\n",
    "\n",
    "        tb = 0\n",
    "        tb = insert(tb, 1)\n",
    "        tb = insert(tb, 9)\n",
    "        print(isValidInsert(tb, 1, 9))\n",
    "        \n",
    "        curStates = collections.deque([(0, -1)])\n",
    "        # print(curStates)\n",
    "        # print(isValidBoard(int('100000001', 2)))\n",
    "        ret = 0\n",
    "        for i in range(1, m):\n",
    "            dqn = len(curStates)\n",
    "            for _ in range(dqn):\n",
    "                iniState, last = curStates.popleft()\n",
    "                for newP in range(1, 10):\n",
    "                    if isEmptyPoint(iniState, newP):\n",
    "                        newState = insert(iniState, newP)\n",
    "                        if last == -1: curStates.append((newState, newP))\n",
    "                        elif isValidInsert(newState, last, newP):\n",
    "                            curStates.append((newState, newP))\n",
    "        # print(curStates)\n",
    "        for i in range(m, n+1):\n",
    "            dqn = len(curStates)\n",
    "            for _ in range(dqn):\n",
    "                iniState, last = curStates.popleft()\n",
    "                for newP in range(1, 10):\n",
    "                    if isEmptyPoint(iniState, newP):\n",
    "                        newState = insert(iniState, newP)\n",
    "                        # print(newState)\n",
    "                        if last == -1: curStates.append((newState, newP))\n",
    "                        elif isValidInsert(newState, last, newP):\n",
    "                            curStates.append((newState, newP))\n",
    "            ret+=len(curStates)\n",
    "        # print(curStates)\n",
    "        return ret\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def applyOperations(self, nums: List[int]) -> List[int]:\n",
    "        return_val = []\n",
    "        idx = 0\n",
    "        for i in range(len(nums) - 1):\n",
    "            if nums[i] == 0:\n",
    "                return_val.append(0)\n",
    "            elif nums[i] == nums[i + 1]:\n",
    "                nums[i + 1] = 0\n",
    "                return_val.insert(idx, 2 * nums[i])\n",
    "                idx += 1\n",
    "            else:\n",
    "                return_val.insert(idx, nums[i])\n",
    "                idx += 1\n",
    "        return_val.insert(idx, nums[-1]) if nums[-1] != 0 else return_val.append(0)\n",
    "        return return_val"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def isArmstrong(self, n: int) -> bool:\n",
    "        n_l = []\n",
    "        m = n \n",
    "        while m >= 1:\n",
    "            n_l.insert(0, m%10)\n",
    "            m //= 10\n",
    "        sums = 0\n",
    "        for i in n_l:\n",
    "            sums += i**len(n_l)\n",
    "        return n == sums"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def asteroidCollision(self, asteroids: List[int]) -> List[int]:\n",
    "        rs = [asteroids.pop()]\n",
    "        while asteroids:\n",
    "            cur_asteroid = asteroids.pop()\n",
    "            for i in range(len(rs)):\n",
    "                asteroid = rs[0]\n",
    "                # 左边向右，右边向左，碰撞\n",
    "                if cur_asteroid>0 and asteroid<0:\n",
    "                    if abs(asteroid)>abs(cur_asteroid):  # 当前右边的大，结束\n",
    "                        break\n",
    "                    elif abs(asteroid)==abs(cur_asteroid):  # 相等，消消乐，结束\n",
    "                        rs.pop(0)\n",
    "                        break\n",
    "                    else:\n",
    "                        rs.pop(0)\n",
    "                else:  # 同向或者反向，插入碰撞后(如果有碰撞)留下的星球，结束\n",
    "                    rs.insert(0, cur_asteroid)\n",
    "                    break\n",
    "            else:\n",
    "                rs.insert(0, cur_asteroid)\n",
    "        return rs\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def averageOfLevels(self, root):\n",
    "        \"\"\"\n",
    "        :type root: TreeNode\n",
    "        :rtype: List[float]\n",
    "        \"\"\"\n",
    "        if not root:\n",
    "            return None\n",
    "        queue = [0, root]\n",
    "        result = []\n",
    "        level_node = []\n",
    "        while len(queue) != 0:\n",
    "            node = queue.pop()\n",
    "\n",
    "            if node != 0:\n",
    "                level_node.append(node.val)\n",
    "\n",
    "                if node.left:\n",
    "                    queue.insert(0, node.left)\n",
    "                if node.right:\n",
    "                    queue.insert(0, node.right)\n",
    "            else:\n",
    "                if len(queue) != 0:\n",
    "                    queue.insert(0,0)\n",
    "                result.append(sum(level_node) / len(level_node))\n",
    "                level_node = []\n",
    "        return result\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from sortedcontainers import SortedList\n",
    "from enum import Enum\n",
    "class Color(Enum):\n",
    "    Red = 1\n",
    "    Black = 2\n",
    "\n",
    "\n",
    "T = TypeVar(\"T\")\n",
    "\n",
    "\n",
    "class RBTreeNode(Generic[T]):\n",
    "    def __init__(self, key: T, color: Color = Color.Black, size: int = 0,\n",
    "                 p: Optional[\"RBTreeNode\"] = None, left: Optional[\"RBTreeNode\"] = None, right: Optional[\"RBTreeNode\"] = None):\n",
    "        self.key = key\n",
    "        self.color = color\n",
    "        # x.size = x.left.size + x.right.size + 1\n",
    "        self.size = size  # 树的大小.\n",
    "        self.p: \"RBTreeNode\" = p\n",
    "        self.left: \"RBTreeNode\" = left\n",
    "        self.right: \"RBTreeNode\" = right\n",
    "\n",
    "\n",
    "\"\"\"红黑树特性\n",
    "1. 特殊的二叉搜索树(BST). 保证没有一条路径会比其他路径长2倍, 因此是平衡的.\n",
    "2. 若某节点无子节点/父节点, 则对应指针指向nil(用nil节点代替None, 使得代码结构更清晰)\n",
    "    空树: root=nil. \n",
    "3. 根节点, nil为黑色. 若某节点为红, 则取两节点为黑. \n",
    "    对于每个节点, 该节点到nil的路径上, 具有相同黑色节点. \n",
    "\"\"\"\n",
    "\n",
    "\n",
    "class RBTree(Generic[T]):\n",
    "    \"\"\"\n",
    "    Ref: 算法导论\n",
    "    note: 可重复. 类似于c++的multiset\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self):\n",
    "        # 空树\n",
    "        nil = RBTreeNode(0, Color.Black)\n",
    "        self.root = nil\n",
    "        self.nil = nil\n",
    "\n",
    "    def getitem(self, i: int) -> RBTreeNode:\n",
    "        return self._getitem(self.root, i)\n",
    "\n",
    "    def _getitem(self, tn: RBTreeNode, i: int) -> RBTreeNode:\n",
    "        \"\"\"返回x为根的子树的第i小关键字(从0开始)(即SortedList中sl[i])的节点\"\"\"\n",
    "        idx = tn.left.size  # 当前节点的索引\n",
    "        if i == idx:\n",
    "            return tn\n",
    "        elif i < idx:\n",
    "            return self._getitem(tn.left, i)\n",
    "        else:\n",
    "            return self._getitem(tn.right, i - idx - 1)\n",
    "\n",
    "    def bisect_left(self, x: T) -> int:\n",
    "        \"\"\"获取SortedList中x值的lower bound索引.\"\"\"\n",
    "        tn = self.root\n",
    "        res = 0\n",
    "        while tn is not self.nil:\n",
    "            if x <= tn.key:\n",
    "                tn = tn.left\n",
    "            else:\n",
    "                res += tn.left.size + 1\n",
    "                tn = tn.right\n",
    "        return res\n",
    "\n",
    "    def bisect_right(self, x: T) -> int:\n",
    "        \"\"\"获取SortedList中x值的upper bound索引.\"\"\"\n",
    "        tn = self.root\n",
    "        res = 0\n",
    "        while tn is not self.nil:\n",
    "            if x < tn.key:\n",
    "                tn = tn.left\n",
    "            else:\n",
    "                res += tn.left.size + 1\n",
    "                tn = tn.right\n",
    "        return res\n",
    "\n",
    "    def search(self, x: T) -> RBTreeNode:\n",
    "        \"\"\"搜索key=k的tn\"\"\"\n",
    "        tn = self.root\n",
    "        while tn is not self.nil and x != tn.key:\n",
    "            if x < tn.key:\n",
    "                tn = tn.left\n",
    "            else:\n",
    "                tn = tn.right\n",
    "        return tn\n",
    "\n",
    "    def _left_rotate(self, x: RBTreeNode) -> None:\n",
    "        \"\"\"左旋. x为旋转根\"\"\"\n",
    "        y = x.right\n",
    "        assert y is not self.nil  # 假设\n",
    "        x.right = y.left\n",
    "        if y.left is not self.nil:\n",
    "            y.left.p = x\n",
    "        y.p = x.p\n",
    "        if x.p is self.nil:\n",
    "            self.root = y\n",
    "        elif x is x.p.left:\n",
    "            x.p.left = y\n",
    "        else:\n",
    "            x.p.right = y\n",
    "        y.left = x\n",
    "        x.p = y\n",
    "        y.size = x.size\n",
    "        x.size = x.left.size + x.right.size + 1\n",
    "\n",
    "    def _right_rotate(self, y: RBTreeNode) -> None:\n",
    "        \"\"\"右旋, y为旋转根\"\"\"\n",
    "        x = y.left\n",
    "        assert x is not self.nil\n",
    "        y.left = x.right\n",
    "        if x.right is not self.nil:\n",
    "            x.right.p = y\n",
    "        x.p = y.p\n",
    "        if y.p is self.nil:\n",
    "            self.root = x\n",
    "        elif y is y.p.left:\n",
    "            y.p.left = x\n",
    "        else:\n",
    "            y.p.right = x\n",
    "        x.right = y\n",
    "        y.p = x\n",
    "        x.size = y.size\n",
    "        y.size = y.left.size + y.right.size + 1\n",
    "\n",
    "    def insert(self, z: RBTreeNode) -> None:\n",
    "        \"\"\"插入z节点\"\"\"\n",
    "        y = self.nil\n",
    "        x = self.root\n",
    "        # 找位置.\n",
    "        while x is not self.nil:\n",
    "            y = x\n",
    "            x.size += 1\n",
    "            if z.key < x.key:\n",
    "                x = x.left\n",
    "            else:\n",
    "                x = x.right\n",
    "        # 插入\n",
    "        z.p = y\n",
    "        if y is self.nil:\n",
    "            self.root = z\n",
    "        elif z.key < y.key:\n",
    "            y.left = z\n",
    "        else:\n",
    "            y.right = z\n",
    "        z.left = self.nil\n",
    "        z.right = self.nil\n",
    "        z.color = Color.Red  # 置为红, z可能违背红黑性质\n",
    "        z.size = 1\n",
    "        self._rb_insert_fixup(z)\n",
    "\n",
    "    def _rb_insert_fixup(self, z: RBTreeNode) -> None:\n",
    "        # z: 可能违背红黑性质的节点\n",
    "        while z.p.color is Color.Red:\n",
    "            if z.p is z.p.p.left:\n",
    "                y = z.p.p.right\n",
    "                if y.color is Color.Red:\n",
    "                    z.p.color = Color.Black\n",
    "                    y.color = Color.Black\n",
    "                    z.p.p.color = Color.Red\n",
    "                    z = z.p.p\n",
    "                elif z is z.p.right:\n",
    "                    z = z.p\n",
    "                    self._left_rotate(z)\n",
    "                else:\n",
    "                    z.p.color = Color.Black\n",
    "                    z.p.p.color = Color.Red\n",
    "                    self._right_rotate(z.p.p)\n",
    "            else:\n",
    "                y = z.p.p.left\n",
    "                if y.color is Color.Red:\n",
    "                    z.p.color = Color.Black\n",
    "                    y.color = Color.Black\n",
    "                    z.p.p.color = Color.Red\n",
    "                    z = z.p.p\n",
    "                elif z is z.p.left:\n",
    "                    z = z.p\n",
    "                    self._right_rotate(z)\n",
    "                else:\n",
    "                    z.p.color = Color.Black\n",
    "                    z.p.p.color = Color.Red\n",
    "                    self._left_rotate(z.p.p)\n",
    "        self.root.color = Color.Black\n",
    "\n",
    "    def _rb_transplant(self, u: RBTreeNode, v: RBTreeNode) -> None:\n",
    "        # 用v替代u, 删除节点时使用\n",
    "        if u.p is self.nil:\n",
    "            self.root = v\n",
    "        elif u is u.p.left:\n",
    "            u.p.left = v\n",
    "        else:\n",
    "            u.p.right = v\n",
    "        v.p = u.p\n",
    "\n",
    "    def _tree_minimum(self, x: RBTreeNode) -> RBTreeNode:\n",
    "        \"\"\"找二叉搜索树中的最小值(一直往左找)\"\"\"\n",
    "        while x.left is not self.nil:\n",
    "            x = x.left\n",
    "        return x\n",
    "\n",
    "    def delete(self, z: RBTreeNode) -> None:\n",
    "        \"\"\"删除z\"\"\"\n",
    "        # y: 在树中删除的节点或者移至树内的节点\n",
    "        # x: 移到y的原始位置上\n",
    "        y = z\n",
    "        y_original_color = y.color\n",
    "        if z.left is self.nil:\n",
    "            x = z.right\n",
    "            self._rb_transplant(z, z.right)\n",
    "        elif z.right is self.nil:\n",
    "            x = z.left\n",
    "            self._rb_transplant(z, z.left)\n",
    "        else:\n",
    "            y = self._tree_minimum(z.right)\n",
    "            y_original_color = y.color\n",
    "            x = y.right\n",
    "            if y.p is z:\n",
    "                x.p = y\n",
    "            else:\n",
    "                self._rb_transplant(y, y.right)\n",
    "                y.right = z.right\n",
    "                y.right.p = y\n",
    "            self._rb_transplant(z, y)\n",
    "            y.left = z.left\n",
    "            y.left.p = y\n",
    "            y.color = z.color\n",
    "            y.size = z.size\n",
    "        p = x.p\n",
    "        while p is not self.nil:\n",
    "            p.size -= 1\n",
    "            p = p.p\n",
    "        #\n",
    "        if y_original_color is Color.Black:\n",
    "            self._rb_delete_fixup(x)  # 删了一个黑\n",
    "\n",
    "    def _rb_delete_fixup(self, x: RBTreeNode) -> None:\n",
    "        while x is not self.root and x.color is Color.Black:\n",
    "            if x is x.p.left:\n",
    "                w = x.p.right\n",
    "                if w.color is Color.Red:\n",
    "                    w.color = Color.Black\n",
    "                    x.p.color = Color.Red\n",
    "                    self._left_rotate(x.p)\n",
    "                    w = x.p.right\n",
    "                if w.left.color is Color.Black and w.right.color is Color.Black:\n",
    "                    w.color = Color.Red\n",
    "                    x = x.p\n",
    "                elif w.right.color is Color.Black:\n",
    "                    w.left.color = Color.Black\n",
    "                    w.color = Color.Red\n",
    "                    self._right_rotate(w)\n",
    "                    w = x.p.right\n",
    "                else:\n",
    "                    w.color = x.p.color\n",
    "                    x.p.color = Color.Black\n",
    "                    w.right.color = Color.Black\n",
    "                    self._left_rotate(x.p)\n",
    "                    x = self.root\n",
    "            else:\n",
    "                w = x.p.left\n",
    "                if w.color is Color.Red:\n",
    "                    w.color = Color.Black\n",
    "                    x.p.color = Color.Red\n",
    "                    self._right_rotate(x.p)\n",
    "                    w = x.p.left\n",
    "                if w.right.color is Color.Black and w.left.color is Color.Black:\n",
    "                    w.color = Color.Red\n",
    "                    x = x.p\n",
    "                elif w.left.color is Color.Black:\n",
    "                    w.right.color = Color.Black\n",
    "                    w.color = Color.Red\n",
    "                    self._left_rotate(w)\n",
    "                    w = x.p.left  # 保证一致性\n",
    "                else:\n",
    "                    w.color = x.p.color\n",
    "                    x.p.color = Color.Black\n",
    "                    w.left.color = Color.Black\n",
    "                    self._right_rotate(x.p)\n",
    "                    x = self.root\n",
    "        x.color = Color.Black\n",
    "\n",
    "    def _inorder_traversal(self, tn: RBTreeNode, res: List[T]) -> None:\n",
    "        if tn is self.nil:\n",
    "            return\n",
    "        self._inorder_traversal(tn.left, res)\n",
    "        res.append(tn.key)\n",
    "        self._inorder_traversal(tn.right, res)\n",
    "\n",
    "    def __repr__(self) -> str:\n",
    "        \"\"\"中序遍历\"\"\"\n",
    "        res = []\n",
    "        self._inorder_traversal(self.root, res)\n",
    "        return repr(res)\n",
    "\n",
    "\n",
    "class RBSortedList(Generic[T]):\n",
    "    def __init__(self, nums: Optional[List[T]] = None) -> None:\n",
    "        if nums is None:\n",
    "            nums = []\n",
    "        self.rbt = RBTree()\n",
    "        for x in nums:\n",
    "            self.add(x)\n",
    "\n",
    "    def add(self, x: T) -> None:\n",
    "        self.rbt.insert(RBTreeNode(x))\n",
    "\n",
    "    def remove(self, x: T) -> None:\n",
    "        tn = self.rbt.search(x)\n",
    "        assert tn is not self.rbt.nil\n",
    "        self.rbt.delete(tn)\n",
    "\n",
    "    def bisect_left(self, x: T) -> int:\n",
    "        return self.rbt.bisect_left(x)\n",
    "\n",
    "    def bisect_right(self, x: T) -> int:\n",
    "        return self.rbt.bisect_right(x)\n",
    "\n",
    "    def pop(self, i: int) -> T:\n",
    "        tn = self.rbt.getitem(i)\n",
    "        res = tn.key\n",
    "        self.rbt.delete(tn)\n",
    "        return res\n",
    "\n",
    "    def __len__(self) -> int:\n",
    "        return self.rbt.root.size\n",
    "\n",
    "    def __getitem__(self, i: int) -> T:\n",
    "        if i < 0:\n",
    "            i = i + len(self)\n",
    "        if i >= len(self):\n",
    "            raise IndexError\n",
    "        return self.rbt.getitem(i).key\n",
    "\n",
    "    def __repr__(self) -> str:\n",
    "        return f\"{self.__class__.__name__}({self.rbt!r})\"\n",
    "\n",
    "class SimpleSortedList(Generic[T]):\n",
    "    \"\"\"使用二分法搜索实现有序的list.\n",
    "        or 使用库: sortedcontainers\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, nums: Optional[List[T]] = None) -> None:\n",
    "        if nums is None:\n",
    "            nums = []\n",
    "        self.sl: List[T] = nums\n",
    "        self.sl.sort()\n",
    "\n",
    "    def add(self, x: T) -> None:\n",
    "        idx = self.bisect_right(x)\n",
    "        self.sl.insert(idx, x)\n",
    "\n",
    "    def remove(self, x: T) -> None:\n",
    "        # 只删一个. 同sortedcontainers.SortedList\n",
    "        idx = self.bisect_right(x) - 1\n",
    "        if self.sl[idx] != x:\n",
    "            raise ValueError(\"x not find\")\n",
    "        self.sl.pop(idx)\n",
    "\n",
    "    def bisect_left(self, x: T) -> int:\n",
    "        \"\"\"return: [0..len(self)]\"\"\"\n",
    "        return bisect_left(self.sl, x)\n",
    "\n",
    "    def bisect_right(self, x: T) -> int:\n",
    "        \"\"\"return: [0..len(self)]\"\"\"\n",
    "        return bisect_right(self.sl, x)\n",
    "\n",
    "    def pop(self, i: int) -> T:\n",
    "        return self.sl.pop(i)\n",
    "\n",
    "    def __len__(self) -> int:\n",
    "        return len(self.sl)\n",
    "\n",
    "    def __getitem__(self, idx: int) -> T:\n",
    "        return self.sl[idx]\n",
    "\n",
    "    def __repr__(self) -> str:\n",
    "        return f\"{self.__class__.__name__}({self.sl})\"\n",
    "\n",
    "class Solution:\n",
    "    def avoidFlood(self, rains: List[int]) -> List[int]:\n",
    "        \"\"\"将抽的天数存起来. \n",
    "        -: lake_date: 对于每一个湖. 最近的下雨的日期. \n",
    "            sum_set: 晴天的池, 存日期. \n",
    "        若遇到某天下雨, 但是湖以及满了, 则查看上一次下雨和这次下雨之间由于空闲的晴天, 在那一天倒水. \n",
    "            若有则清除晴天. 没有则失败.        \n",
    "        \"\"\"\n",
    "        n = len(rains)\n",
    "        res = [-1] * n\n",
    "        lake_date = DefaultDict[int, int]()\n",
    "        sum_date = RBSortedList()\n",
    "        for date in range(n):\n",
    "            lake_idx = rains[date]\n",
    "            if lake_idx == 0:\n",
    "                sum_date.add(date)\n",
    "            else:\n",
    "                if lake_idx not in lake_date:\n",
    "                    lake_date[lake_idx] = date\n",
    "                else:\n",
    "                    last_date = lake_date[lake_idx]\n",
    "                    i = sum_date.bisect_left(last_date)\n",
    "                    if i < len(sum_date):  # 存在\n",
    "                        lake_date[lake_idx] = date\n",
    "                        d = sum_date[i]\n",
    "                        res[d] = lake_idx\n",
    "                        sum_date.pop(i)\n",
    "                    else:\n",
    "                        return []\n",
    "        # 剩下的sum_set, 随意抽光一个湖, 这里取第一个湖\n",
    "        for date in sum_date:\n",
    "            res[date] = 1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def avoidFlood(self, rains: List[int]) -> List[int]:\n",
    "        N = len(rains)\n",
    "        lake = dict()\n",
    "        day = defaultdict(set)\n",
    "\n",
    "        ans = [1] * N\n",
    "        head = Node(-1)\n",
    "        for i, r in enumerate(rains):\n",
    "            #print(f\"{i}, {r}\")\n",
    "            if r == 0:\n",
    "                #print(f\"inset: {head.prv.i}->{i}\")\n",
    "                head.prv.insert(i)\n",
    "                continue\n",
    "            ans[i] = -1\n",
    "            if r not in lake:\n",
    "                lake[r] = head.prv\n",
    "                day[head.prv.i].add(r)\n",
    "            else:\n",
    "                p = lake[r]\n",
    "                #print(f\"got point: {p.i}\")\n",
    "                if p.nxt == head:\n",
    "                    return []\n",
    "                else:\n",
    "                    n = p.nxt.dettach()\n",
    "                    ans[n.i] = r\n",
    "                    day[p.i].remove(r)\n",
    "                    #print(f\"use {n.i}\")\n",
    "                    lake[r] = head.prv\n",
    "                    day[head.prv.i].add(r)\n",
    "                    for x in day[n.i]:\n",
    "                        lake[x] = p\n",
    "                        day[p.i].add(x)\n",
    "                    day[n.i].clear()\n",
    "        return ans\n",
    "\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, i, prv=None, nxt=None):\n",
    "        self.i = i\n",
    "        self.prv = prv or self\n",
    "        self.nxt = nxt or self\n",
    "    \n",
    "    def dettach(self):\n",
    "        self.prv.nxt = self.nxt\n",
    "        self.nxt.prv = self.prv\n",
    "        return self\n",
    "    \n",
    "    def insert(self, i):\n",
    "        n = Node(i, prv=self, nxt=self.nxt)\n",
    "        self.nxt.prv = n\n",
    "        self.nxt = n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def balanceBST(self, root: TreeNode) -> TreeNode:\n",
    "        dic={}\n",
    "        dic=collections.defaultdict(int)\n",
    "        #functions\n",
    "        def getheight(root):\n",
    "            \n",
    "            return max(dic[root.left],dic[root.right])+1\n",
    "        def isavl(root):\n",
    "            return abs(dic[root.left]-dic[root.right])<2\n",
    "        def insert(root,val):\n",
    "            if not root:\n",
    "                #true insert\n",
    "                root=TreeNode(val)\n",
    "                dic[root]=1\n",
    "                #need to update height\n",
    "                #return root\n",
    "            else:\n",
    "                #先insert 完值  然后再判断是否为超过height  这里有个逻辑问题\n",
    "                #对于当前root节点，先查看他是走左边节点还是右边  \n",
    "                #然后要是走左边，判断走左边还是右边 -- LL LR情况 ，如果LR，则给他Insert进去 然后再进行左旋，旋转再右旋：：\n",
    "                #这里使用递归来做 ，问题就出在了这里了。 不管那么多 出来了再检查\n",
    "                if val<root.val:\n",
    "                    root.left=insert(root.left,val)\n",
    "                    if not isavl(root):\n",
    "                        #LR情况    \n",
    "                        if val > root.left.val:\n",
    "                            #leftr first\n",
    "                            root.left=leftr(root.left)\n",
    "                        #LL情况  这里 记住 ，root对应 节点是变的\n",
    "                        root=rightr(root)\n",
    "                elif val >root.val:\n",
    "                    root.right=insert(root.right,val)\n",
    "                    if not isavl(root):\n",
    "                        if val < root.right.val:\n",
    "                            root.right=rightr(root.right)\n",
    "                        root=leftr(root) \n",
    "                else:#same node\n",
    "                    return root\n",
    "            #update height recursively\n",
    "            #在这里更新 需要想的一个问题是 当他们在旋转过程中，切换了root节点的位置时 是否会有冲突 造成影响\n",
    "            dic[root]=getheight(root)\n",
    "            return root\n",
    "\n",
    "                    \n",
    "        #返回的是 旋转后的节点值            \n",
    "        def leftr(root):\n",
    "            right=root.right\n",
    "            root.right=right.left\n",
    "            right.left=root\n",
    "            #update root\n",
    "            #rooth=getheight(root)\n",
    "            dic[root]=getheight(root)\n",
    "            #\n",
    "            dic[right]=getheight(right)\n",
    "            return right\n",
    "        def rightr(root):\n",
    "            left=root.left\n",
    "            root.left=left.right\n",
    "            left.right=root\n",
    "            dic[root]=getheight(root)\n",
    "            dic[left]=getheight(left)\n",
    "            return left\n",
    "        #首先 我们要定义左旋右旋，我差不多也知道\n",
    "        #OK 30分钟 解决手撕AVL的问题好吗 不做完不吃饭\n",
    "        #注意了，首先打好基础： right left | insert |\n",
    "\n",
    "\n",
    "\n",
    "        #################遍历 获取节点\n",
    "        li=[]\n",
    "        def tra(root):\n",
    "            if not root:\n",
    "                return \n",
    "            tra(root.left)\n",
    "            li.append(root.val)\n",
    "            tra(root.right)\n",
    "        print(root)\n",
    "        tra(root)\n",
    "        print('li:',li)\n",
    "        ##### main\n",
    "        self.root=None\n",
    "        \n",
    "        #mid insert:\n",
    "        def midinsert(l,h):\n",
    "            if l>h:\n",
    "                return\n",
    "            \n",
    "            mid=l+h\n",
    "            mid//=2\n",
    "            #print(li,li[mid],l,h)\n",
    "            #root=midinsert(li[mid])\n",
    "            #print(li[mid])\n",
    "            self.li.append(li[mid])\n",
    "            #self.root = insert(self.root,li[mid])\n",
    "            #print('root:',self.root.val)\n",
    "            midinsert(l,mid-1)\n",
    "            midinsert(mid+1,h)\n",
    "            return self.root\n",
    "        self.li=[]\n",
    "        \n",
    "        midinsert(0,len(li)-1)\n",
    "        # 通过了 BUT 有 BUG，现在就是找BUG时间\n",
    "        root=None\n",
    "        #n=len(li)-1\n",
    "        print(self.li)\n",
    "        #n=1\n",
    "        for r in self.li:\n",
    "            root=insert(root,r)\n",
    "            #li=[]\n",
    "            #tra(root)\n",
    "            #print(li)\n",
    "            #if not n :\n",
    "            #    break\n",
    "            #n-=1\n",
    "            #print(root)\n",
    "        return root\n",
    "\n",
    "\n",
    "\n",
    "        # build mid  ，通过中序  直接建立树\n",
    "        ###############################\n",
    "        def build(l,h):\n",
    "            if l>h:\n",
    "                return\n",
    "            mid=l+h\n",
    "            mid//=2\n",
    "            #rt=TreeNode(self.li[mid])\n",
    "            rt=li[mid]\n",
    "            \n",
    "            rt.left=build(l,mid-1)\n",
    "            rt.right=build(mid+1,h)\n",
    "            return rt\n",
    "        return build(0,len(li)-1)\n",
    "\n",
    "\n",
    "        ###############################\n",
    "        def isBst(root):\n",
    "            if not root:\n",
    "                return True,0\n",
    "            l,lh=isBst(root.left)\n",
    "            r,rh=isBst(root.right)\n",
    "            if r and l and abs(lh-rh)<2:\n",
    "                return 1,max(r,l)+1\n",
    "            else:\n",
    "                return 0,root\n",
    "                #这里我们看看 到底是需要返回什么\n",
    "                #以及搜索树的话， 有值我们就可以找到很快的\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def balanceBST(self, root: TreeNode) -> TreeNode:\n",
    "        dic={}\n",
    "        dic=collections.defaultdict(int)\n",
    "        #functions\n",
    "        def getheight(root):\n",
    "            \n",
    "            return max(dic[root.left],dic[root.right])+1\n",
    "        def isavl(root):\n",
    "            return abs(dic[root.left]-dic[root.right])<2\n",
    "        def insert(root,val):\n",
    "            if not root:\n",
    "                #true insert\n",
    "                root=TreeNode(val)\n",
    "                dic[root]=1\n",
    "                #need to update height\n",
    "                #return root\n",
    "            else:\n",
    "                #先insert 完值  然后再判断是否为超过height  这里有个逻辑问题\n",
    "                #对于当前root节点，先查看他是走左边节点还是右边  \n",
    "                #然后要是走左边，判断走左边还是右边 -- LL LR情况 ，如果LR，则给他Insert进去 然后再进行左旋，旋转再右旋：：\n",
    "                #这里使用递归来做 ，问题就出在了这里了。 不管那么多 出来了再检查\n",
    "                if val<root.val:\n",
    "                    root.left=insert(root.left,val)\n",
    "                    if not isavl(root):\n",
    "                        #LR情况    \n",
    "                        if val > root.left.val:\n",
    "                            #leftr first\n",
    "                            root.left=leftr(root.left)\n",
    "                        #LL情况  这里 记住 ，root对应 节点是变的\n",
    "                        root=rightr(root)\n",
    "                elif val >root.val:\n",
    "                    root.right=insert(root.right,val)\n",
    "                    if not isavl(root):\n",
    "                        if val < root.right.val:\n",
    "                            root.right=rightr(root.right)\n",
    "                        root=leftr(root) \n",
    "                else:#same node\n",
    "                    return root\n",
    "            #update height recursively\n",
    "            #在这里更新 需要想的一个问题是 当他们在旋转过程中，切换了root节点的位置时 是否会有冲突 造成影响\n",
    "            dic[root]=getheight(root)\n",
    "            return root\n",
    "\n",
    "                    \n",
    "        #返回的是 旋转后的节点值            \n",
    "        def leftr(root):\n",
    "            right=root.right\n",
    "            root.right=right.left\n",
    "            right.left=root\n",
    "            #update root\n",
    "            #rooth=getheight(root)\n",
    "            dic[root]=getheight(root)\n",
    "            #\n",
    "            dic[right]=getheight(right)\n",
    "            return right\n",
    "        def rightr(root):\n",
    "            left=root.left\n",
    "            root.right=left.right\n",
    "            left.right=root\n",
    "            dic[root]=getheight(root)\n",
    "            dic[left]=getheight(left)\n",
    "            return left\n",
    "        #首先 我们要定义左旋右旋，我差不多也知道\n",
    "        #OK 30分钟 解决手撕AVL的问题好吗 不做完不吃饭\n",
    "        #注意了，首先打好基础： right left | insert |\n",
    "\n",
    "\n",
    "\n",
    "        #################遍历 获取节点\n",
    "        li=[]\n",
    "        def tra(root):\n",
    "            if not root:\n",
    "                return \n",
    "            tra(root.left)\n",
    "            li.append(root.val)\n",
    "            tra(root.right)\n",
    "        print(root)\n",
    "        tra(root)\n",
    "        print('li:',li)\n",
    "        ##### main\n",
    "        self.root=None\n",
    "        \n",
    "        #mid insert:\n",
    "        def midinsert(l,h):\n",
    "            if l>h:\n",
    "                return\n",
    "            mid=l+h\n",
    "            mid//=2\n",
    "            #print(li,li[mid],l,h)\n",
    "            #root=midinsert(li[mid])\n",
    "            self.root = insert(self.root,li[mid])\n",
    "            #print('root:',self.root.val)\n",
    "            midinsert(l,mid-1)\n",
    "            midinsert(mid+1,h)\n",
    "            return self.root\n",
    "        '''midinsert(0,len(li)-1)\n",
    "        return self.root\n",
    "'''\n",
    "\n",
    "        root=None\n",
    "        for r in li:\n",
    "            root=insert(root,r)\n",
    "            #print(root)\n",
    "        return root\n",
    "\n",
    "\n",
    "\n",
    "        # build mid  ，通过中序  直接建立树\n",
    "        ###############################\n",
    "        def build(l,h):\n",
    "            if l>h:\n",
    "                return\n",
    "            mid=l+h\n",
    "            mid//=2\n",
    "            #rt=TreeNode(self.li[mid])\n",
    "            rt=li[mid]\n",
    "            \n",
    "            rt.left=build(l,mid-1)\n",
    "            rt.right=build(mid+1,h)\n",
    "            return rt\n",
    "        return build(0,len(li)-1)\n",
    "\n",
    "\n",
    "        ###############################\n",
    "        def isBst(root):\n",
    "            if not root:\n",
    "                return True,0\n",
    "            l,lh=isBst(root.left)\n",
    "            r,rh=isBst(root.right)\n",
    "            if r and l and abs(lh-rh)<2:\n",
    "                return 1,max(r,l)+1\n",
    "            else:\n",
    "                return 0,root\n",
    "                #这里我们看看 到底是需要返回什么\n",
    "                #以及搜索树的话， 有值我们就可以找到很快的\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def order(self,root,s):\n",
    "        if root==None:\n",
    "            return\n",
    "        self.order(root.left,s)\n",
    "        s.append(root.val)\n",
    "        self.order(root.right,s)\n",
    "    def insert(self,root,val):\n",
    "        if root==None:\n",
    "            return TreeNode(val)\n",
    "        if val<root.val:\n",
    "            root.left=self.insert(root.left,val)\n",
    "        if val>root.val:\n",
    "            root.right=self.insert(root.right,val)\n",
    "        return root\n",
    "    def create(self,s,root):\n",
    "        if s==None:\n",
    "            return root\n",
    "        if len(s)==0:\n",
    "            return root\n",
    "        mid=int(len(s)/2)\n",
    "        root=self.insert(root,s[mid])\n",
    "        root=self.create(s[0:mid],root)\n",
    "        root=self.create(s[mid+1:],root)\n",
    "        return root\n",
    "    def balanceBST(self, root: TreeNode) -> TreeNode:\n",
    "        s=[]\n",
    "        self.order(root,s)\n",
    "        head=None\n",
    "        head=self.create(s,head)\n",
    "        return head\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countQuadruplets(self, nums: List[int]) -> int:\n",
    "        l = []\n",
    "        dp = {}\n",
    "        ret = 0\n",
    "\n",
    "        for i, n in enumerate(nums):\n",
    "            p = bisect.bisect_left(l, n)\n",
    "\n",
    "            for i in range(p):\n",
    "                ret += dp[l[i]][2]\n",
    "\n",
    "            for i in range(p, len(l)):\n",
    "                dpi = dp[l[i]]\n",
    "                dpi[2] += bisect.bisect_left(dpi[1], n)\n",
    "\n",
    "            dp[n] = [1, l[:p], 0]\n",
    "            l.insert(p, n)\n",
    "\n",
    "        return ret\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from bisect import bisect\n",
    "class CountIntervals:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.lst = []\n",
    "        self.cnt = 0\n",
    "\n",
    "    def extend(self, idx, right):\n",
    "        a, b = self.lst[idx]\n",
    "        assert right > b\n",
    "        if idx + 1 == len(self.lst):\n",
    "            self.lst[idx] = (a, right)\n",
    "            self.cnt += right - b\n",
    "            return\n",
    "        a2, b2 = self.lst[idx+1]\n",
    "        if right + 1 < a2:\n",
    "            self.lst[idx] = (a, right)\n",
    "            self.cnt += right - b\n",
    "            return\n",
    "        self.lst[idx:idx+2] = [(a, b2)] # replace 2 with 1\n",
    "        self.cnt += a2 - b - 1\n",
    "        if right > b2:\n",
    "            self.extend(idx, right)\n",
    "\n",
    "    def add(self, left: int, right: int) -> None:\n",
    "        if not self.lst:\n",
    "            self.lst.append((left,right))\n",
    "            self.cnt = right - left + 1\n",
    "            return\n",
    "        idx = bisect(self.lst, left, key=lambda a: a[0])\n",
    "\n",
    "        if idx > 0:\n",
    "            a,b = self.lst[idx-1]\n",
    "            if left <= b+1:\n",
    "                if right > b:\n",
    "                    self.extend(idx-1, right)\n",
    "                return\n",
    "        if idx == len(self.lst):\n",
    "            self.lst[idx:idx] = [(left, right)]  # insert\n",
    "            self.cnt += right - left + 1\n",
    "            return\n",
    "        a,b = self.lst[idx]\n",
    "        if right + 1 < a:\n",
    "            self.lst[idx:idx] = [(left,right)] # insert\n",
    "            self.cnt += right - left + 1\n",
    "        else:\n",
    "            self.lst[idx] = (left, b)\n",
    "            self.cnt += a - left\n",
    "            if right > b:\n",
    "                self.extend(idx, right)\n",
    "\n",
    "    def count(self) -> int:\n",
    "        return self.cnt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from bisect import bisect\n",
    "class CountIntervals:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.lst = []\n",
    "        self.cnt = 0\n",
    "\n",
    "    def extend(self, idx, right):\n",
    "        a, b = self.lst[idx]\n",
    "        assert right > b\n",
    "        if idx + 1 == len(self.lst):\n",
    "            self.lst[idx] = (a, right)\n",
    "            self.cnt += right - b\n",
    "            return\n",
    "        a2, b2 = self.lst[idx+1]\n",
    "        if right + 1 < a2:\n",
    "            self.lst[idx] = (a, right)\n",
    "            self.cnt += right - b\n",
    "            return\n",
    "        self.lst[idx:idx+2] = [(a, b2)] # replace 2 with 1\n",
    "        self.cnt += a2 - b - 1\n",
    "        if right > b2:\n",
    "            self.extend(idx, right)\n",
    "\n",
    "    def add(self, left: int, right: int) -> None:\n",
    "        if not self.lst:\n",
    "            self.lst.append((left,right))\n",
    "            self.cnt = right - left + 1\n",
    "            return\n",
    "        idx = bisect(self.lst, left, key=lambda a: a[0])\n",
    "\n",
    "        if idx > 0:\n",
    "            a,b = self.lst[idx-1]\n",
    "            if left <= b+1:\n",
    "                if right > b:\n",
    "                    self.extend(idx-1, right)\n",
    "                return\n",
    "        if idx == len(self.lst):\n",
    "            self.lst[idx:idx] = [(left, right)]  # insert\n",
    "            self.cnt += right - left + 1\n",
    "            return\n",
    "        a,b = self.lst[idx]\n",
    "        if right + 1 < a:\n",
    "            self.lst[idx:idx] = [(left,right)] # insert\n",
    "            self.cnt += right - left + 1\n",
    "        else:\n",
    "            self.lst[idx] = (left, b)\n",
    "            self.cnt += a - left\n",
    "            if right > b:\n",
    "                self.extend(idx, right)\n",
    "\n",
    "    def count(self) -> int:\n",
    "        return self.cnt\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your CountIntervals object will be instantiated and called as such:\n",
    "# obj = CountIntervals()\n",
    "# obj.add(left,right)\n",
    "# param_2 = obj.count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from bisect import bisect\n",
    "class CountIntervals:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.lst = []\n",
    "        self.cnt = 0\n",
    "\n",
    "    def extend(self, idx, right):\n",
    "        a, b = self.lst[idx]\n",
    "        assert right > b\n",
    "        if idx + 1 == len(self.lst):\n",
    "            self.lst[idx] = (a, right)\n",
    "            self.cnt += right - b\n",
    "            return\n",
    "        a2, b2 = self.lst[idx+1]\n",
    "        if right + 1 < a2:\n",
    "            self.lst[idx] = (a, right)\n",
    "            self.cnt += right - b\n",
    "            return\n",
    "        self.lst[idx:idx+2] = [(a, b2)] # replace 2 with 1\n",
    "        self.cnt += a2 - b - 1\n",
    "        if right > b2:\n",
    "            self.extend(idx, right)\n",
    "\n",
    "    def add(self, left: int, right: int) -> None:\n",
    "        if not self.lst:\n",
    "            self.lst.append((left,right))\n",
    "            self.cnt = right - left + 1\n",
    "            return\n",
    "        idx = bisect(self.lst, left, key=lambda a: a[0])\n",
    "\n",
    "        if idx > 0:\n",
    "            a,b = self.lst[idx-1]\n",
    "            if left <= b+1:\n",
    "                if right > b:\n",
    "                    self.extend(idx-1, right)\n",
    "                return\n",
    "        if idx == len(self.lst):\n",
    "            self.lst[idx:idx] = [(left, right)]  # insert\n",
    "            self.cnt += right - left + 1\n",
    "            return\n",
    "        a,b = self.lst[idx]\n",
    "        if right + 1 < a:\n",
    "            self.lst[idx:idx] = [(left,right)] # insert\n",
    "            self.cnt += right - left + 1\n",
    "        else:\n",
    "            self.lst[idx] = (left, b)\n",
    "            self.cnt += a - left\n",
    "            if right > b:\n",
    "                self.extend(idx, right)\n",
    "\n",
    "    def count(self) -> int:\n",
    "        return self.cnt\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# class CountIntervals:\n",
    "\n",
    "#     def __init__(self):\n",
    "#         self.intervals=[]\n",
    "\n",
    "#     def add(self, left: int, right: int) :\n",
    "#         i=0\n",
    "#         while i<len(self.intervals) and self.intervals[i][1]<left:\n",
    "#             i++1\n",
    "#         merged_interval=[left,right]\n",
    "#         while i<len(self.intervals) and self.intervals[i][0]<=right:\n",
    "#             merged_interval[0]=min([merged_interval],self.intervals[i][0])\n",
    "#             merged_interval[1]=max([merged_interval],self.intervals[i][1])\n",
    "#             self.intervals.pop(i)\n",
    "#         self.intervals.insert(i, merged_interval)  \n",
    "\n",
    "#     def count(self):\n",
    "#         count=0\n",
    "#         for interval in self.intervals:\n",
    "#             count +=interval[1] - interval[0]+1\n",
    "#         return count        \n",
    "\n",
    "\n",
    "\n",
    "# Your CountIntervals object will be instantiated and called as such:\n",
    "# obj = CountIntervals()\n",
    "# obj.add(left,right)\n",
    "# param_2 = obj.count()\n",
    "# class CountIntervals:\n",
    "#     def __init__(self):\n",
    "#         self.intervals = []\n",
    "\n",
    "#     def add(self, left, right):\n",
    "#         # 合并重叠区间\n",
    "#         merged_intervals = []\n",
    "#         inserted = False\n",
    "#         for interval in self.intervals:\n",
    "#             if interval[1] < left:\n",
    "#                 merged_intervals.append(interval)\n",
    "#             elif interval[0] <= right:\n",
    "#                 left = min(left, interval[0])\n",
    "#                 right = max(right, interval[1])\n",
    "#             else:\n",
    "#                 if not inserted:\n",
    "#                     merged_intervals.append([left, right])\n",
    "#                     inserted = True\n",
    "#                 merged_intervals.append(interval)\n",
    "        \n",
    "#         if not inserted:\n",
    "#             merged_intervals.append([left, right])\n",
    "        \n",
    "#         self.intervals = merged_intervals\n",
    "\n",
    "#     def count(self):\n",
    "#         count = 0\n",
    "#         for interval in self.intervals:\n",
    "#             count += interval[1] - interval[0] + 1\n",
    "#         return count\n",
    "\n",
    "from sortedcontainers import SortedDict\n",
    "\n",
    "class CountIntervals:\n",
    "    def __init__(self):\n",
    "        self.d = SortedDict()\n",
    "        self.cnt = 0  # 所有区间长度和\n",
    "\n",
    "    def add(self, left: int, right: int) -> None:\n",
    "        # 遍历所有被 [left,right] 覆盖到的区间（部分覆盖也算）\n",
    "        i = self.d.bisect_left(left)\n",
    "        while i < len(self.d) and self.d.values()[i] <= right:\n",
    "            r, l = self.d.items()[i]\n",
    "            left = min(left, l)    # 合并后的新区间，其左端点为所有被覆盖的区间的左端点的最小值\n",
    "            right = max(right, r)  # 合并后的新区间，其右端点为所有被覆盖的区间的右端点的最大值\n",
    "            self.cnt -= r - l + 1\n",
    "            self.d.popitem(i)\n",
    "        self.cnt += right - left + 1\n",
    "        self.d[right] = left  # 所有被覆盖到的区间与 [left,right] 合并成一个新区间\n",
    "\n",
    "    def count(self) -> int:\n",
    "        return self.cnt\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class CountIntervals:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.L = []\n",
    "        self.cnt = 0\n",
    "\n",
    "    def add(self, left: int, right: int) -> None:\n",
    "        pos = bisect_right(self.L,left,key = lambda x:x[1])\n",
    "        if pos and left == self.L[pos-1][1]:\n",
    "            self.cnt += right-left\n",
    "            self.L[pos-1][1] = right\n",
    "        else:\n",
    "            self.L.insert(pos,[left,right])\n",
    "            if pos + 1 < len(self.L) and self.L[pos+1][0] <= self.L[pos][0]:\n",
    "                if self.L[pos+1][1] >= self.L[pos][1]:\n",
    "                    self.L.pop(pos);return\n",
    "                else:\n",
    "                    self.L[pos][0] = self.L[pos+1][0]\n",
    "                    self.cnt += left-self.L[pos+1][0]\n",
    "            self.cnt += right-left+1\n",
    "\n",
    "            while pos + 1 < len(self.L) and self.L[pos+1][0] <= self.L[pos][1]:\n",
    "                otl,otr = self.L.pop(pos+1)\n",
    "                self.cnt -= min(otr,self.L[pos][1])-otl+1\n",
    "                self.L[pos][1] = max(self.L[pos][1],otr)\n",
    "        # print(self.L,self.cnt)\n",
    "\n",
    "    def count(self) -> int:\n",
    "        return self.cnt\n",
    "\n",
    "\n",
    "# Your CountIntervals object will be instantiated and called as such:\n",
    "# obj = CountIntervals()\n",
    "# obj.add(left,right)\n",
    "# param_2 = obj.count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:\n",
    "        S={\"left\":None, \"right\":None, \"values\":[0, 1, 1]}\n",
    "        s=0\n",
    "        ret=0\n",
    "        def search(v, root):\n",
    "            if root is None:\n",
    "                return 0\n",
    "            if v<=root[\"values\"][0]:\n",
    "                ret=search(v, root[\"left\"])\n",
    "                if root[\"right\"] is not None:\n",
    "                    ret+=root[\"right\"][\"values\"][1]\n",
    "                return ret+1\n",
    "            else:\n",
    "                return search(v, root[\"right\"])\n",
    "                \n",
    "        def insert(v, root):\n",
    "            if root is None:\n",
    "                return {\"left\":None, \"right\":None, \"values\":[v, 1, 1]}\n",
    "            root[\"values\"][1]+=1\n",
    "            if v<=root[\"values\"][0]:\n",
    "                root[\"left\"]=insert(v, root[\"left\"])                   \n",
    "            else:\n",
    "                root[\"right\"]=insert(v, root[\"right\"])\n",
    "            ## balance\n",
    "            lnum=0 if root[\"left\"] is None else root[\"left\"][\"values\"][2]\n",
    "            rnum=0 if root[\"right\"] is None else root[\"right\"][\"values\"][2]\n",
    "            root[\"values\"][2]=max(lnum, rnum)+1\n",
    "            if lnum-rnum>1:\n",
    "                tmp=root[\"left\"]\n",
    "                root[\"left\"]=tmp[\"right\"]\n",
    "                tmp[\"right\"]=root\n",
    "\n",
    "                tnum=0 if root[\"left\"] is None else root[\"left\"][\"values\"][2]\n",
    "                tsize=0 if root[\"left\"] is None else root[\"left\"][\"values\"][1]\n",
    "                rsize=0 if root[\"right\"] is None else root[\"right\"][\"values\"][1]\n",
    "                tlsize=0 if tmp[\"left\"] is None else tmp[\"left\"][\"values\"][1]\n",
    "                root[\"values\"][2]=max(rnum, tnum)+1\n",
    "                root[\"values\"][1]=tsize+rsize+1\n",
    "                tmp[\"values\"][2]=max(tmp[\"values\"][2], tmp[\"right\"][\"values\"][2]+1)\n",
    "                tmp[\"values\"][1]=tlsize+tsize+rsize+2\n",
    "                root=tmp\n",
    "            elif rnum-lnum>1:\n",
    "                tmp=root[\"right\"]\n",
    "                root[\"right\"]=tmp[\"left\"]\n",
    "                tmp[\"left\"]=root\n",
    "\n",
    "                tnum=0 if root[\"right\"] is None else root[\"right\"][\"values\"][2]\n",
    "                tsize=0 if root[\"left\"] is None else root[\"left\"][\"values\"][1]\n",
    "                rsize=0 if root[\"right\"] is None else root[\"right\"][\"values\"][1]\n",
    "                tlsize=0 if tmp[\"right\"] is None else tmp[\"right\"][\"values\"][1]\n",
    "                root[\"values\"][2]=max(lnum, tnum)+1\n",
    "                root[\"values\"][1]=tsize+rsize+1\n",
    "                tmp[\"values\"][2]=max(tmp[\"values\"][2], tmp[\"left\"][\"values\"][2]+1)\n",
    "                tmp[\"values\"][1]=tlsize+tsize+rsize+2\n",
    "                root=tmp\n",
    "            return root\n",
    "        \n",
    "        for v in nums:\n",
    "            s+=v\n",
    "            lidx, uidx=s-lower+1, s-upper\n",
    "            lidx, uidx=search(lidx, S), search(uidx, S)\n",
    "            ret+=uidx-lidx\n",
    "            S=insert(s, S)\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class IntervalTree:\n",
    "    def __init__(self, size):\n",
    "        self.size = size\n",
    "        self.interval_tree = [0 for _ in range(size*4)]\n",
    "\n",
    "    def insert(self,p,l,r,index):\n",
    "        if index < l or r < index:\n",
    "            return \n",
    "        interval_tree = self.interval_tree        \n",
    "        if l == r:\n",
    "            interval_tree[p] += 1\n",
    "            return\n",
    "        mid = (l+r)//2\n",
    "        if index <= mid:\n",
    "            self.insert(p*2,l,mid,index)\n",
    "        else:\n",
    "            self.insert(p*2+1,mid+1,r,index)\n",
    "        interval_tree[p] = interval_tree[p*2]+interval_tree[p*2+1]       \n",
    "    \n",
    "    def query(self,p,l,r,x,y):\n",
    "        if y < l or r < x:\n",
    "            return 0\n",
    "        if x<=l and r<=y:\n",
    "            return self.interval_tree[p]\n",
    "        mid = (l+r)//2\n",
    "        s = 0\n",
    "        if x <= mid:\n",
    "            s += self.query(p*2,l,mid,x,y)\n",
    "        if mid < y:\n",
    "            s += self.query(p*2+1,mid+1,r,x,y)\n",
    "        return s\n",
    "\n",
    "class Solution:\n",
    "    def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:         \n",
    "        s = list(accumulate(nums,initial=0))\n",
    "        hashes = s + [ x-lower for x in s] + [ x-upper for x in s]\n",
    "        hashes = sorted(list(set(hashes)))\n",
    "        # 生成前缀和，问题转化为，对于每个j，找左边的i,判断 s[j]-upper<=s[i]<=s[j]-lower,统计这些i的数量\n",
    "        # 把所有前缀和数组中的数字插入线段树，并对这些数字划分区间，线段树维护当前区间数字数量，\n",
    "        # 所以需要对这些数字都散列化\n",
    "        tree_size = len(hashes)\n",
    "        tree = IntervalTree(tree_size)\n",
    "        cnt = 0\n",
    "        for i in s:\n",
    "            x = bisect_left(hashes,i-upper)\n",
    "            y = bisect_left(hashes,i-lower)\n",
    "            j = bisect_left(hashes,i)\n",
    "            c = tree.query(1,1,tree_size, x+1,y+1)\n",
    "            # print(x,y,j,c)\n",
    "            cnt += c\n",
    "            tree.insert(1,1,tree_size,j+1)\n",
    "\n",
    "        return cnt\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:\n",
    "        import numpy as np\n",
    "        nums = list(np.cumsum(nums))\n",
    "        nums.insert(0, 0)\n",
    "        tmp = nums.copy()\n",
    "        count = 0\n",
    "\n",
    "        def sort(nums, lo, hi):\n",
    "            if lo == hi:\n",
    "                return\n",
    "            mid = lo + (hi - lo) // 2\n",
    "            sort(nums, lo, mid)\n",
    "            sort(nums, mid + 1, hi)\n",
    "            merge(nums, lo, mid, hi)\n",
    "\n",
    "        def merge(nums, lo, mid, hi):\n",
    "            nonlocal count\n",
    "            tmp[lo:hi + 1] = nums[lo:hi + 1]\n",
    "            start = mid + 1\n",
    "            end = mid + 1\n",
    "            for i in range(lo, mid + 1):\n",
    "                while start <= hi and nums[start] - nums[i] < lower :\n",
    "                    start += 1\n",
    "                while end <= hi and nums[end] - nums[i] <= upper :\n",
    "                    end += 1\n",
    "                count += end - start\n",
    "            i = lo\n",
    "            j = mid + 1\n",
    "            for p in range(lo, hi + 1):\n",
    "                if i == mid + 1:\n",
    "                    nums[p] = tmp[j]\n",
    "                    j += 1\n",
    "                elif j == hi + 1:\n",
    "                    nums[p] = tmp[i]\n",
    "                    i += 1\n",
    "                elif tmp[i] <= tmp[j]:\n",
    "                    nums[p] = tmp[i]\n",
    "                    i += 1\n",
    "                else:\n",
    "                    nums[p] = tmp[j]\n",
    "                    j += 1\n",
    "\n",
    "        sort(nums,0, len(nums) - 1)\n",
    "        return count"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# class SegNode:\r\n",
    "#     def __init__(self,left,right) -> None:\r\n",
    "#         self.left=left\r\n",
    "#         self.right=right\r\n",
    "#         self.left_node=None\r\n",
    "#         self.right_node=None\r\n",
    "#         self.sum=0\r\n",
    "    \r\n",
    "#     @classmethod\r\n",
    "#     def build(cls,left,right):\r\n",
    "#         node=SegNode(left,right)\r\n",
    "#         if left==right:\r\n",
    "#             return node\r\n",
    "#         mid=(left+right)//2\r\n",
    "#         l_node=SegNode.build(left,mid)\r\n",
    "#         r_node=SegNode.build(mid+1,right)\r\n",
    "#         node.left_node=l_node\r\n",
    "#         node.right_node=r_node\r\n",
    "#         return node\r\n",
    "    \r\n",
    "#     def count(self,left,right):\r\n",
    "#         if self.right< left or self.left>right:\r\n",
    "#             return 0\r\n",
    "#         if self.left>=left and self.right<=right:\r\n",
    "#             return self.sum\r\n",
    "#         return self.left_node.count(left,right)+self.right_node.count(left,right)\r\n",
    "\r\n",
    "#     def insert(self,index):\r\n",
    "#         self.sum+=1\r\n",
    "#         if self.left==self.right:\r\n",
    "#             return\r\n",
    "#         mid=(self.left+self.right)//2\r\n",
    "#         if index<=mid:\r\n",
    "#             self.left_node.insert(index)\r\n",
    "#         else:\r\n",
    "#             self.right_node.insert(index)\r\n",
    "\r\n",
    "\r\n",
    "class Tree:\r\n",
    "    def __init__(self,count) -> None:\r\n",
    "        self.tree=[0]*(count+1)\r\n",
    "        self.len=count+1\r\n",
    "    \r\n",
    "    def _lowbit(self,index):\r\n",
    "        return index&-index\r\n",
    "\r\n",
    "    def add(self,index):\r\n",
    "        while index<self.len:\r\n",
    "            self.tree[index]+=1\r\n",
    "            index+=self._lowbit(index)\r\n",
    "    \r\n",
    "    def query(self,index):\r\n",
    "        ret=0\r\n",
    "        while index>0:\r\n",
    "            ret+=self.tree[index]\r\n",
    "            index-=self._lowbit(index)\r\n",
    "        return ret\r\n",
    "\r\n",
    "class Solution:\r\n",
    "    def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:\r\n",
    "        # ret=0\r\n",
    "        N=len(nums)\r\n",
    "        presum=[0]*(N+1)\r\n",
    "        # l_bound,r_bound=float('inf'),float('-inf')\r\n",
    "        for i in range(N):\r\n",
    "            sum=nums[i]+presum[i]\r\n",
    "            presum[i+1]=sum\r\n",
    "            # l=sum-upper\r\n",
    "            # r=sum-lower\r\n",
    "            # l_bound=min(l_bound,sum,l,r)\r\n",
    "            # r_bound=max(r_bound,sum,l,r)\r\n",
    "        \r\n",
    "        all_nums=set()\r\n",
    "        for sum in presum:\r\n",
    "            all_nums.add(sum)\r\n",
    "            all_nums.add(sum-lower)\r\n",
    "            all_nums.add(sum-upper)\r\n",
    "\r\n",
    "        all_nums=sorted(all_nums)\r\n",
    "        num_idx={}\r\n",
    "        idx=0\r\n",
    "        for n in all_nums:\r\n",
    "            num_idx[n]=idx\r\n",
    "            idx+=1\r\n",
    "        \r\n",
    "        Len=len(num_idx.values())\r\n",
    "        # node=SegNode.build(l_bound,r_bound)\r\n",
    "        tree=Tree(Len)\r\n",
    "\r\n",
    "        ret=0\r\n",
    "        for n in presum:\r\n",
    "            ret+=tree.query(num_idx[n-lower]+1)-tree.query(num_idx[n-upper])\r\n",
    "            tree.add(num_idx[n]+1)\r\n",
    "        return ret\r\n",
    "\r\n",
    "\r\n",
    "        \r\n",
    "\r\n",
    "\r\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countSmaller(self, nums):\n",
    "        \"\"\"\n",
    "        :type nums: List[int]\n",
    "        :rtype: List[int]\n",
    "        \"\"\"\n",
    "        import bisect\n",
    "        n = len(nums)\n",
    "        ans = [None]*n\n",
    "        tmp = []\n",
    "        for i in range(n-1, -1, -1):\n",
    "            t = nums[i]\n",
    "            pos = bisect.bisect_left(tmp, t)\n",
    "            ans[i] = pos\n",
    "            tmp.insert(pos, t)\n",
    "\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countSmaller(self, nums: List[int]) -> List[int]:\n",
    "        # 新建一个排序的空列表\n",
    "        # 从右到左，添加原列表元素到该空列表中（二分查找）\n",
    "        # 添加位置即表示结果\n",
    "        n = len(nums)\n",
    "\n",
    "        sortNums = []\n",
    "        rs = [0] * n\n",
    "\n",
    "        for i in range(n - 1, -1, -1):\n",
    "            num = nums[i]\n",
    "            index = bisect.bisect_left(sortNums, num)\n",
    "            sortNums.insert(index, num)\n",
    "            rs[i] = index\n",
    "        return rs\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countSmaller(self, nums: List[int]) -> List[int]:\n",
    "        sortns = []\n",
    "        res = []\n",
    "        for num in reversed(nums):\n",
    "            idx = bisect.bisect_left(sortns, num)\n",
    "            res.append(idx)\n",
    "            sortns.insert(idx, num)\n",
    "            \n",
    "        return res[::-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from typing import List\n",
    "\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, coordinates: List[List[int]], _k: int) -> int:\n",
    "        hmap = {}\n",
    "        res = 0\n",
    "        for pair in coordinates:\n",
    "            first = self.first_key(pair)\n",
    "            if first in hmap:\n",
    "                bucket = hmap[first]\n",
    "                for k in bucket:\n",
    "                    if (pair[0] ^ (first[0] + k[0])) + (pair[1] ^ (first[1] + k[1])) == _k:\n",
    "                        res += bucket[k]\n",
    "            self.insert(hmap, pair)\n",
    "        return res\n",
    "\n",
    "    def first_key(self, pair: List[int]):\n",
    "        return (pair[0] & ~127, pair[1] & ~127)\n",
    "    def secord_key(self, pair: List[int]):\n",
    "        return (pair[0] & 127, pair[1] & 127)\n",
    "\n",
    "    def insert(self, hmap, pair: List[int]):\n",
    "        first = self.first_key(pair)\n",
    "        second = self.secord_key(pair)\n",
    "        \n",
    "        if first not in hmap:\n",
    "            hmap[first] = {}\n",
    "        if second not in hmap[first]:\n",
    "            hmap[first][second] = 0\n",
    "        hmap[first][second] += 1\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "HIGH_BIT = 15\n",
    "\n",
    "class Trie:\n",
    "    __slots__ = 'children', 'cnt'\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        # 经过当前节点的数的数量\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, x):\n",
    "        '''将数字 x 按照二进制位从高到低的顺序插入到字典树中'''\n",
    "        node = self\n",
    "        for i in range(HIGH_BIT, -1, -1):\n",
    "            v = x >> i & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def searchXOr(self, x, limit):\n",
    "        '''在字典树中查找与数字 x 的异或值小于 limit 的数量'''\n",
    "        node = self\n",
    "        ans = 0\n",
    "        for i in range(HIGH_BIT, -1, -1):\n",
    "            if node is None:\n",
    "                return ans\n",
    "            v = x >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    ans += node.children[v].cnt\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                node = node.children[v]\n",
    "\n",
    "        return ans\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        t = Trie()\n",
    "        ans = 0\n",
    "        for num in nums:\n",
    "            ans += t.searchXOr(num, high + 1) - t.searchXOr(num, low)\n",
    "            t.insert(num)\n",
    "\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie :\n",
    "    __slots__ = (\"children\",\"cnt\",)\n",
    "\n",
    "    def __init__(self) :\n",
    "        self.children = [None] * 2 \n",
    "        self.cnt = 0\n",
    "    def insert(self , x) :\n",
    "        node = self \n",
    "        for i in range(15 , -1 , -1) :\n",
    "            u = x >> i & 1 \n",
    "            if node.children[u] is None :\n",
    "                node.children[u] = Trie()\n",
    "            node = node.children[u]\n",
    "            node.cnt += 1 \n",
    "    def search(self , x , limit) :\n",
    "        node , ans = self , 0 \n",
    "        for i in range(15 , -1 , -1 ):\n",
    "            if node is None :\n",
    "                return ans \n",
    "            u = x >> i & 1 \n",
    "            if limit >> i & 1 :\n",
    "                if node.children[u] :\n",
    "                    ans += node.children[u].cnt\n",
    "                node = node.children[u ^ 1]\n",
    "            else :\n",
    "                node = node.children[u]\n",
    "        return ans \n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans = 0 \n",
    "        tree = Trie()\n",
    "        for x in nums :\n",
    "            ans += tree.search(x , high + 1) - tree.search(x , low)\n",
    "            tree.insert(x)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    __slots__ = 'children', 'cnt', 'high_bit'\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        # 经过当前节点的数的数量\n",
    "        self.cnt = 0\n",
    "        # 给定数据范围的最高二进制位数\n",
    "        self.high_bit = 15\n",
    "\n",
    "    def insert(self, x):\n",
    "        '''将数字 x 按照二进制位从高到低的顺序插入到字典树中'''\n",
    "        node = self\n",
    "        for i in range(self.high_bit, -1, -1):\n",
    "            v = x >> i & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def searchXOr(self, x, limit):\n",
    "        '''在字典树中查找与数字 x 的异或值小于 limit 的数量'''\n",
    "        node = self\n",
    "        ans = 0\n",
    "        for i in range(self.high_bit, -1, -1):\n",
    "            if node is None:\n",
    "                return ans\n",
    "            v = x >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    ans += node.children[v].cnt\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                node = node.children[v]\n",
    "\n",
    "        return ans\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        t = Trie()\n",
    "        ans = 0\n",
    "        for num in nums:\n",
    "            ans += t.searchXOr(num, high + 1) - t.searchXOr(num, low)\n",
    "            t.insert(num)\n",
    "\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        # 经过当前节点的数的数量\n",
    "        self.cnt = 0\n",
    "        # 给定数据范围的最高二进制位数\n",
    "        self.high_bit = 15\n",
    "\n",
    "    def insert(self, x):\n",
    "        '''\n",
    "        将数字 x 按照二进制位从高到低的顺序插入到字典树中\n",
    "        '''\n",
    "        node = self\n",
    "        for i in range(self.high_bit, -1, -1):\n",
    "            v = x >> i & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def searchXOr(self, x, limit):\n",
    "        '''\n",
    "        在字典树中查找与数字 x 的异或值小于 limit 的数量\n",
    "        '''\n",
    "        node = self\n",
    "        ans = 0\n",
    "        for i in range(self.high_bit, -1, -1):\n",
    "            if node is None:\n",
    "                return ans\n",
    "            v = x >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    ans += node.children[v].cnt\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                node = node.children[v]\n",
    "\n",
    "        return ans\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        t = Trie()\n",
    "        ans = 0\n",
    "        for num in nums:\n",
    "            ans += t.searchXOr(num, high + 1) - t.searchXOr(num, low)\n",
    "            t.insert(num)\n",
    "\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):        \n",
    "        self.child = [None, None]\n",
    "        self.count = 0\n",
    "    \n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def insert(root: Optional[Trie], n: int) -> NoReturn:\n",
    "            for i in range(15, -1, -1):\n",
    "                x = bool((n) & (1 << i))\n",
    "                if not root.child[x]:\n",
    "                    root.child[x] = Trie()\n",
    "                root.child[x].count += 1\n",
    "                root = root.child[x]\n",
    "\n",
    "        def count_k(root: Optional[Trie], n: int, k: int) -> int:\n",
    "            result = 0\n",
    "            for i in range(15, -1, -1):       \n",
    "                if not root:\n",
    "                    break                       \n",
    "                x = bool(n & (1 << i))\n",
    "                y = k & (1 << i)\n",
    "                if y:\n",
    "                    if root.child[x]:\n",
    "                        result += root.child[x].count\n",
    "                    root = root.child[1 - x]\n",
    "                else:\n",
    "                    root = root.child[x]\n",
    "            return result\n",
    "        root = Trie()\n",
    "        result = 0\n",
    "        for num in nums:\n",
    "            result += count_k(root, num, high + 1) - count_k(root, num, low)\n",
    "            insert(root, num)\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):        \n",
    "        self.child = [None, None]\n",
    "        self.count = 0\n",
    "    \n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def insert(root: Optional[Trie], n: int) -> NoReturn:\n",
    "            for i in range(15, -1, -1):\n",
    "                x = bool((n) & (1 << i))\n",
    "                if not root.child[x]:\n",
    "                    root.child[x] = Trie()\n",
    "                root.child[x].count += 1\n",
    "                root = root.child[x]\n",
    "\n",
    "        def helper(root: Optional[Trie], cur: int, x: int) -> int:\n",
    "            result = 0\n",
    "            for i in range(15, -1, -1):       \n",
    "                if not root:\n",
    "                    break                       \n",
    "                k = bool(cur & (1 << i))\n",
    "                if x & (1 << i):\n",
    "                    if root.child[k]:\n",
    "                        result += root.child[k].count\n",
    "                    root = root.child[1 - k]\n",
    "                else:\n",
    "                    root = root.child[k]\n",
    "            return result\n",
    "        root = Trie()\n",
    "        result = 0\n",
    "        for num in nums:\n",
    "            result += helper(root, num, high + 1) - helper(root, num, low)\n",
    "            insert(root, num)\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\n",
    "class tr_node():\n",
    "    def __init__(self):\n",
    "        self.bit=[None,None]\n",
    "        self.sum=0\n",
    "class trie_01():\n",
    "    def __init__(self):\n",
    "        self.root=tr_node()\n",
    "    def insert(self,x):\n",
    "        u=self.root\n",
    "        i=24\n",
    "        while i>=0:\n",
    "            k=x>>i&1\n",
    "            if u.bit[k]==None:\n",
    "                u.bit[k]=tr_node()\n",
    "            u=u.bit[k]\n",
    "            u.sum+=1\n",
    "            i-=1\n",
    "    def query(self,x,k):\n",
    "        ans=0\n",
    "        u=self.root\n",
    "        i=24\n",
    "        while i>=0:\n",
    "            kb=k>>i&1\n",
    "            cb=x>>i&1\n",
    "            if kb==1:\n",
    "                if u.bit[cb]:\n",
    "                    ans+=u.bit[cb].sum\n",
    "                if u.bit[cb^1]==None:\n",
    "                    return ans\n",
    "                u=u.bit[cb^1]\n",
    "            else:\n",
    "                if u.bit[cb]==None:\n",
    "                    return ans\n",
    "                u=u.bit[cb]\n",
    "            i-=1\n",
    "        ans+=u.sum\n",
    "        return ans\n",
    "        \n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans=0\n",
    "        n=len(nums)\n",
    "        tr=trie_01()\n",
    "        for i in nums:\n",
    "            ans+=tr.query(i,high)-tr.query(i,low-1)\n",
    "            tr.insert(i)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):        \n",
    "        self.child = [None, None]\n",
    "        self.count = 0\n",
    "    \n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        def insert(root: Optional[Trie], n: int) -> NoReturn:\n",
    "            for i in range(31, -1, -1):\n",
    "                x = bool((n) & (1 << i))\n",
    "                if not root.child[x]:\n",
    "                    root.child[x] = Trie()\n",
    "                root.child[x].count += 1\n",
    "                root = root.child[x]\n",
    "\n",
    "        def count_k(root: Optional[Trie], n: int, k: int) -> int:\n",
    "            result = 0\n",
    "            for i in range(31, -1, -1):       \n",
    "                if not root:\n",
    "                    break                       \n",
    "                x = bool(n & (1 << i))\n",
    "                y = k & (1 << i)\n",
    "                if y:\n",
    "                    if root.child[x]:\n",
    "                        result += root.child[x].count\n",
    "                    root = root.child[1 - x]\n",
    "                else:\n",
    "                    root = root.child[x]\n",
    "            return result\n",
    "        root = Trie()\n",
    "        result = 0\n",
    "        for num in nums:\n",
    "            result += count_k(root, num, high + 1) - count_k(root, num, low)\n",
    "            insert(root, num)\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        trie = Trie()\n",
    "        ans = 0\n",
    "        for i in nums:\n",
    "            \n",
    "            a = trie.search(i, high + 1) - trie.search(i, low)\n",
    "          \n",
    "            ans += a\n",
    "            trie.insert(i)\n",
    "\n",
    "        return ans\n",
    "\n",
    "K = 14        \n",
    "class Trie:\n",
    "    \n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        self.cnt = 0 # 统计漂亮数对的个数\n",
    "    \n",
    "    def insert(self, x):\n",
    "        node = self\n",
    "        # for i in range(K, -1, -1):\n",
    "        #     ch = (x >> K) & 1\n",
    "        #     if node.children[ch] is None:\n",
    "        #         node.children[ch] = Trie()\n",
    "        #     node = node.children[ch]\n",
    "        #     node.cnt += 1\n",
    "        for k in range(14, -1, -1):\n",
    "            v = (x >> k) & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "            # node.cnt += 1 # 我觉得在前面加一和后面加一效果差不多\n",
    "            # 关于在前在后加一，可以使用边界判断的方法\n",
    "            # 对于叶子节点，前置位放置此语句叶子结点值不会改变\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def search(self, x, compare):\n",
    "        # 每次插入一个元素，从高位到低位计算异或值\n",
    "        # 如果f(x, compare):表示x和compare的比较,\n",
    "        # 比较二者之间的异或值，\n",
    "        ans = 0\n",
    "        node = self\n",
    "        for i in range(K, -1, -1):\n",
    "            \n",
    "            if node is None:\n",
    "                return ans\n",
    "\n",
    "            ch = (x >> i) & 1\n",
    "            if (compare >> i) & 1: # 若是1的话，对于任何x的当前位数都满足小于等于compare\n",
    "                if node.children[ch] is not None: # 说明两数在当前位是相同的，1 xor 1 = 0，直接返回当前结点下的所有数即可\n",
    "                    ans += node.children[ch].cnt\n",
    "                node = node.children[ch^1]\n",
    "            else: # 若是0的话，当且仅当，两数当前位相同的情况下，才有可能进行\n",
    "                node = node.children[ch]\n",
    "        return ans \n",
    "        # node = self\n",
    "        # ans = 0\n",
    "        \n",
    "        # for k in range(14, -1, -1):\n",
    "        #     if node is None:\n",
    "        #         return ans\n",
    "        #     v = (num >> k) & 1\n",
    "            \n",
    "        #     if (x >> k) & 1: # 第k位为1\n",
    "        #         if node.children[v] is not None: # 异或值为0，一定满足小于x\n",
    "        #             ans += node.children[v].cnt\n",
    "        #         node = node.children[v ^ 1] # 对于异或值为1的存在可能满足小于等于x\n",
    "        #     else: # 第k位为0\n",
    "        #         node = node.children[v] # 只有异或值为0时才存在满足的可能\n",
    "        \n",
    "        # return ans\n",
    "\n",
    "        \"\"\"\n",
    "            使用下面这种思路可行吗。\n",
    "        \"\"\"\n",
    "        # def search(self, x, low, high):\n",
    "        # # 每次插入一个元素，从高位到低位计算异或值\n",
    "        # # 如果\n",
    "        # ans = 0\n",
    "        # node = self\n",
    "        # for i in range(K, -1, -1):\n",
    "        #     ch = (x >> K) & 1\n",
    "        #     if node.children[ch]: # 位上元素相同，返回1 xor 1 = 0， 0 xor 0 = 0\n",
    "        #         if ((low >> K) & 1): # 若low值的第K位为1，则两数之间的异或值必不可能大于low值，可直接break\n",
    "        #             return 0\n",
    "        #         node = node.children[ch]\n",
    "        #     else: # 位上元素不同，返回1 xor 0 = 1\n",
    "        #         # 这种情况只需判断是否小于等于high即可\n",
    "        #         if (high >>k) & 1 == 0:\n",
    "        #             return 0\n",
    "                \n",
    "            \n",
    "        #     return 1\n",
    "\n",
    "\n",
    "            # if node.children[ch]: # 位上元素相同，返回1 xor 1 = 0， 0 xor 0 = 0\n",
    "            #     node = node.children[ch]\n",
    "            # else: # 位上元素不同，返回1 xor 0 = 1\n",
    "            #     # 这种情况只需判断是否小于等于high即可\n",
    "            #     if (compare >> k) & 1 == 1:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Tire:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, num):\n",
    "        node = self\n",
    "        for i in range(15, -1, -1):\n",
    "            v = num >> i & 1\n",
    "            if not node.children[v]:\n",
    "                node.children[v] = Tire()\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "    \n",
    "    def search(self, num, limit):\n",
    "        node = self\n",
    "        res = 0\n",
    "        for i in range(15, -1, -1):\n",
    "            v = num >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    res += node.children[v].cnt\n",
    "                if not node.children[v ^ 1]:\n",
    "                    return res\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                if not node.children[v]:\n",
    "                    return res\n",
    "                node = node.children[v]\n",
    "        return res\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "\n",
    "        ans = 0\n",
    "        t = Tire()\n",
    "        for num in nums:\n",
    "            ans += t.search(num, high + 1) - t.search(num, low)\n",
    "            t.insert(num)\n",
    "\n",
    "        return ans "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 2\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, x):\n",
    "        node = self\n",
    "        for i in range(15, -1, -1):\n",
    "            v = x >> i & 1\n",
    "            if node.children[v] is None:\n",
    "                node.children[v] = Trie()\n",
    "            node = node.children[v]\n",
    "            node.cnt += 1\n",
    "\n",
    "    def search(self, x, limit):\n",
    "        node = self\n",
    "        ans = 0\n",
    "        for i in range(15, -1, -1):\n",
    "            if node is None:\n",
    "                return ans\n",
    "            v = x >> i & 1\n",
    "            if limit >> i & 1:\n",
    "                if node.children[v]:\n",
    "                    ans += node.children[v].cnt\n",
    "                node = node.children[v ^ 1]\n",
    "            else:\n",
    "                node = node.children[v]\n",
    "        return ans\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        ans = 0\n",
    "        tree = Trie()\n",
    "        for x in nums:\n",
    "            ans += tree.search(x, high + 1) - tree.search(x, low)\n",
    "            tree.insert(x)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "HIGH_BIT = 15\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = defaultdict(Trie)\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, x):\n",
    "        cur = self\n",
    "        for i in range(HIGH_BIT - 1, -1, -1):\n",
    "            if (x >> i) & 1:\n",
    "                cur = cur.children[1]\n",
    "            else:\n",
    "                cur = cur.children[0]\n",
    "            cur.cnt += 1\n",
    "\n",
    "    def search(self, x, limit):\n",
    "        ans = 0\n",
    "        cur = self\n",
    "        for i in range(HIGH_BIT - 1, -1, -1):\n",
    "            if not cur.children:\n",
    "                return ans\n",
    "            v = (x >> i) & 1\n",
    "            u = (limit >> i) & 1\n",
    "            if u:\n",
    "                if cur.children[v]:\n",
    "                    ans += cur.children[v].cnt\n",
    "                cur = cur.children[v ^ 1]\n",
    "            else:\n",
    "                cur = cur.children[v]\n",
    "        return ans\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        tree = Trie()\n",
    "        res = 0\n",
    "        for x in nums:\n",
    "            res += tree.search(x, high + 1) - tree.search(x, low)\n",
    "            tree.insert(x)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "HIGH_BIT = 15\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = defaultdict(Trie)\n",
    "        self.cnt = 0\n",
    "\n",
    "    def insert(self, x):\n",
    "        cur = self\n",
    "        for i in range(HIGH_BIT - 1, -1, -1):\n",
    "            if (x >> i) & 1:\n",
    "                cur = cur.children[1]\n",
    "            else:\n",
    "                cur = cur.children[0]\n",
    "            cur.cnt += 1\n",
    "\n",
    "    def search(self, x, limit):\n",
    "        ans = 0\n",
    "        cur = self\n",
    "        for i in range(HIGH_BIT - 1, -1, -1):\n",
    "            if not cur.children:\n",
    "                return ans\n",
    "            v = (x >> i) & 1\n",
    "            u = (limit >> i) & 1\n",
    "            if u:\n",
    "                if cur.children[v]:\n",
    "                    ans += cur.children[v].cnt\n",
    "                cur = cur.children[v ^ 1]\n",
    "            else:\n",
    "                cur = cur.children[v]\n",
    "        return ans\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        tree = Trie()\n",
    "        res = 0\n",
    "        for x in nums:\n",
    "            res += tree.search(x, high + 1) - tree.search(x, low)\n",
    "            tree.insert(x)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countPairs(self, nums: List[int], low: int, high: int) -> int:\n",
    "        return self.f(nums, high) - self.f(nums, low-1)\n",
    "\n",
    "    \n",
    "    def f(self, nums, lim):\n",
    "        n = len(nums)\n",
    "        tr = [[0, 0] for _ in range(n * 20 + 5)]\n",
    "        num = [0] * (n*20+5)\n",
    "        cnt, ans = 1, 0\n",
    "\n",
    "        def insert(x):\n",
    "            nonlocal num, tr, cnt\n",
    "            cur = 1\n",
    "            for i in range(16, -1, -1):\n",
    "                t = x >> i & 1\n",
    "                if tr[cur][t] == 0:\n",
    "                    cnt += 1\n",
    "                    tr[cur][t] = cnt\n",
    "                cur = tr[cur][t]\n",
    "                num[cur] += 1\n",
    "        \n",
    "        def query(x):\n",
    "            cur = 1\n",
    "            res = 0\n",
    "            for i in range(16, -1, -1):\n",
    "                t0, t1 = x >> i & 1, lim >> i & 1\n",
    "                t = t0^t1\n",
    "                if t1 == 1:\n",
    "                    res += num[tr[cur][t0]]\n",
    "                if tr[cur][t] == 0:\n",
    "                    return res\n",
    "                cur = tr[cur][t]\n",
    "            return res + num[cur]\n",
    "        \n",
    "        for i in range(n):\n",
    "            ans += query(nums[i])\n",
    "            insert(nums[i])\n",
    "        \n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    # max_heap\n",
    "    def __init__(self):\n",
    "        self.heap = [(0,0)]\n",
    "        self.size = 0\n",
    "\n",
    "    def insert(self, val):\n",
    "        self.heap.append(val)\n",
    "        self.size += 1\n",
    "        self.perc_up(self.size)\n",
    "\n",
    "    def perc_up(self, i):\n",
    "        while i // 2 > 0:\n",
    "            if self.heap[i][1] > self.heap[i//2][1]:\n",
    "                self.heap[i], self.heap[i//2] = self.heap[i//2], self.heap[i]\n",
    "            i = i // 2\n",
    "\n",
    "    def build_max_heap(self, lst):\n",
    "        self.heap = [(0,0)] + lst[:]\n",
    "        self.size = len(lst)\n",
    "        i = self.size // 2\n",
    "        while i > 0:\n",
    "            self.perc_down(i)\n",
    "            i = i - 1\n",
    "\n",
    "    def max_child(self, i):\n",
    "        if i * 2 + 1 > self.size or self.heap[i * 2][1] > self.heap[i * 2 + 1][1]:\n",
    "            return i * 2\n",
    "        else:\n",
    "            return i * 2 + 1\n",
    "\n",
    "    def perc_down(self, i):\n",
    "        while i * 2 <= self.size:\n",
    "            max_child_ind = self.max_child(i)\n",
    "            if self.heap[i][1] < self.heap[max_child_ind][1]:\n",
    "                self.heap[i], self.heap[max_child_ind] = self.heap[max_child_ind], self.heap[i]\n",
    "                i = max_child_ind\n",
    "            else:\n",
    "                break\n",
    "\n",
    "    def del_max(self):\n",
    "        self.heap[1] = self.heap[-1]\n",
    "        self.heap.pop()\n",
    "        self.size -= 1\n",
    "        self.perc_down(1)\n",
    "\n",
    "    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:\n",
    "        if nums == []:\n",
    "            return nums\n",
    "        num_ind = list(enumerate(nums))\n",
    "        res = []\n",
    "        self.build_max_heap(num_ind[:k])\n",
    "        res.append(self.heap[1][1])\n",
    "        for i in range(k, len(nums)):\n",
    "            self.insert(num_ind[i])\n",
    "            while self.heap[1][0] <= i-k:\n",
    "                self.del_max()\n",
    "            res.append(self.heap[1][1])\n",
    "        return res\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:\n",
    "        if len(nums) == 0:\n",
    "            return []\n",
    "        import bisect\n",
    "        import numpy as np\n",
    "        buffer = nums[0:k]\n",
    "        order = list(range(k))\n",
    "        buffer, order = zip(*sorted(zip(buffer, order)))\n",
    "        buffer = list(buffer)\n",
    "        index = np.zeros(k).astype(int)\n",
    "        for i in range(k):\n",
    "            index[order[i]] = i\n",
    "        result = [buffer[-1]]\n",
    "        for i in range(0, len(nums) - k):\n",
    "            erase_pos_in_buffer = index[0]\n",
    "            buffer.pop(erase_pos_in_buffer)\n",
    "            index = index[1:]\n",
    "            index[index > erase_pos_in_buffer] -= 1\n",
    "            insert_pos = bisect.bisect(buffer, nums[k + i])\n",
    "            buffer.insert(insert_pos, nums[k + i])\n",
    "            index[index >= insert_pos] += 1\n",
    "            index = np.append(index, insert_pos)\n",
    "            result.append(buffer[-1])\n",
    "        \n",
    "        return result\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def largestOverlap(self, img1: List[List[int]], img2: List[List[int]]) -> int:\n",
    "        n=len(img1)\n",
    "        \n",
    "        def transfer(x,y):\n",
    "            img=copy.deepcopy(img1)\n",
    "            newlist=[]\n",
    "            if x>=0:\n",
    "                newlist=[[0]*n for _ in range(x)]\n",
    "                newlist.extend(img[0:n-x])\n",
    "            else:\n",
    "                newlist.extend(img[-x:])\n",
    "                newlist.extend([[0]*n for _ in range(-x)])\n",
    "            if y>=0:\n",
    "                for row in newlist:\n",
    "                    for _ in range(y):\n",
    "                        row.insert(0,0)\n",
    "                        row.pop()\n",
    "            else:\n",
    "                for row in newlist:\n",
    "                    for _ in range(-y):\n",
    "                        row.append(0)\n",
    "                        row.pop(0)\n",
    "            \n",
    "            return newlist\n",
    "        \n",
    "        def check(newimg):\n",
    "            return sum(1 for i in range(n) for j in range(n) if newimg[i][j]==img2[i][j]==1)\n",
    "        \n",
    "        return max(check(transfer(x,y)) for x in range(1-n,n) for y in range(1-n,n))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def imageSmoother(self, img: List[List[int]]) -> List[List[int]]:\n",
    "        if img == [[1]]:\n",
    "            return([[1]])\n",
    "        t = []\n",
    "        t1=[]\n",
    "        if len(img) == 1:\n",
    "            t1.append(int((img[0][0] + img[0][1]) // 2))\n",
    "            t1.append(int((img[0][-1] + img[0][-2]) // 2))\n",
    "            for x in range(len(img[0]) - 2):\n",
    "                t1.insert(-1, int((img[0][x] + img[0][x + 1] + img[0][x + 2]) // 3))\n",
    "            t.append(t1)\n",
    "            return(t)\n",
    "        if len(img[0]) == 1:\n",
    "            t.append([int((img[0][0] + img[1][0]) // 2)])\n",
    "            t.append([int((img[-1][0] + img[-2][0]) // 2)])\n",
    "            for x in range(len(img) - 2):\n",
    "                t.insert(-1, [int((img[x + 1][0] + img[x + 2][0]+img[x][0]) // 3)])\n",
    "            return t\n",
    "        xl = len(img[0])\n",
    "        yl = len(img)\n",
    "        for x in range(len(img)):\n",
    "            img[x].insert(0, 0)\n",
    "            img[x].append(0)\n",
    "        img.insert(0, [0] * (xl + 2))\n",
    "        img.append([0] * (xl + 2))\n",
    "        s = 0\n",
    "        t = []\n",
    "        for y in range(yl):\n",
    "            t1 = []\n",
    "            for x in range(xl):\n",
    "                s += img[y][0 + x] + img[y][1 + x] + img[y][2 + x] + \\\n",
    "                    img[y + 1][0 + x] + img[y + 1][1 + x] + img[y + 1][2 + x] \\\n",
    "                    + img[y + 2][0 + x] + img[y + 2][1 + x] + img[y + 2][2 + x]\n",
    "                if y == 0 and x == 0 or y == 0 and x == xl - 1 or y == yl - 1 and x == 0 or y == yl - 1 and x == xl - 1:\n",
    "\n",
    "                    s = int((s / 4) // 1)\n",
    "\n",
    "                elif x == 0 or x == xl - 1 or y == 0 or y == yl - 1:\n",
    "\n",
    "                    s = int((s / 6) // 1)\n",
    "\n",
    "                else:\n",
    "                    s = int((s / 9) // 1)\n",
    "\n",
    "                t1.append(s)\n",
    "                s = 0\n",
    "            t.append(t1)\n",
    "\n",
    "        return t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, c = '', children = []):\n",
    "        self.c = c\n",
    "        self.isLeaf = False\n",
    "        self.children = children.copy() # careful..\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def insert(self, node, string):\n",
    "        # print(string)\n",
    "        # if string == \"\": return\n",
    "        isLeaf = string[1:] == \"\"\n",
    "        hc = string[0]\n",
    "        # print(hc)\n",
    "        for CN in node.children:\n",
    "            if CN.c == hc:\n",
    "                # print(' ',CN.c)\n",
    "                if isLeaf: CN.isLeaf = True\n",
    "                else: self.insert(CN, string[1:])\n",
    "                return\n",
    "        # print('new node', hc)\n",
    "        NN = Node(hc)\n",
    "        node.children.append(NN)\n",
    "        if isLeaf:NN.isLeaf = True\n",
    "        else: self.insert(NN, string[1:])\n",
    "\n",
    "    def check(self, node, string, count=0):\n",
    "        if string == \"\":\n",
    "            isLeaf = node.isLeaf\n",
    "            if not isLeaf: return False\n",
    "            assert count == 0 or count == 1, \"count wrong\"\n",
    "            if count == 0 : return False\n",
    "            return True\n",
    "\n",
    "        hc = string[0]\n",
    "        tmp = []\n",
    "        for CN in node.children:\n",
    "            if CN.c != hc:\n",
    "                if count == 1: continue\n",
    "                tmp.append(self.check(CN, string[1:], count+1))\n",
    "            else:\n",
    "                tmp.append(self.check(CN, string[1:], count))\n",
    "        if True in tmp: return True\n",
    "        return False\n",
    "        \n",
    "    \n",
    "    def __init__(self):\n",
    "        self.root = Node('')\n",
    "\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for s in dictionary:\n",
    "            self.insert(self.root, s)\n",
    "        # print([(n.c,[nn.c for nn in n.children]) for n in self.root.children])\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        return self.check(self.root, searchWord, 0)\n",
    "\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.tree = [[-1 for i in range(26)]]\n",
    "        self.ends = set()\n",
    "    \n",
    "    def insert(self, word):\n",
    "        pos = 0\n",
    "        for c in word:\n",
    "            i = ord(c) - ord('a')\n",
    "            if self.tree[pos][i] == -1:\n",
    "                self.tree.append([-1 for i in range(26)])\n",
    "                self.tree[pos][i] = len(self.tree) - 1\n",
    "            pos = self.tree[pos][i]\n",
    "        self.ends.add(pos)\n",
    "    \n",
    "    def search(self, pos, word, idx, blur_cnt):\n",
    "        #print(\"in search: pos = {} idx = {} blur_cnt = {}\".format(pos, idx, blur_cnt))\n",
    "        #退出条件\n",
    "        if idx == len(word):\n",
    "            return pos in self.ends and blur_cnt == 0\n",
    "        elif pos == len(self.tree):\n",
    "            return False\n",
    "\n",
    "        #正常情况下搜索\n",
    "        ret = False        \n",
    "        i = ord(word[idx]) - ord('a')\n",
    "\n",
    "        for _ in range(26):\n",
    "            if self.tree[pos][_] != -1:\n",
    "                if _ == i:\n",
    "                    ret = ret or self.search(self.tree[pos][_], word, idx + 1, blur_cnt)\n",
    "                elif blur_cnt > 0:\n",
    "                    ret = ret or self.search(self.tree[pos][_], word, idx + 1, blur_cnt - 1)\n",
    "\n",
    "        \"\"\"\n",
    "        if self.tree[pos][i] != -1: #能匹配\n",
    "            ret = ret or self.search(self.tree[pos][i], word, idx + 1, blur_cnt)\n",
    "\n",
    "        if blur_cnt > 0: #能模糊就模糊\n",
    "            for nid in self.tree[pos]:\n",
    "                if nid == -1 or :\n",
    "                    continue\n",
    "                ret = ret or self.search(nid, word, idx + 1, blur_cnt - 1)\n",
    "        \"\"\"\n",
    "\n",
    "        return ret\n",
    "\n",
    "\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.trie = Trie()\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for w in dictionary:\n",
    "            self.trie.insert(w)\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        return self.trie.search(0, searchWord, 0, 1)\n",
    "\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    __slots__ = 'son', 'is_end'\n",
    "\n",
    "    def __init__(self):\n",
    "        self.son = defaultdict(Node)\n",
    "        self.is_end = False\n",
    "\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def insert(self, word):\n",
    "        cur = self.root \n",
    "        for c in word:\n",
    "            cur = cur.son[c]\n",
    "        cur.is_end = True\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for word in dictionary:\n",
    "            self.insert(word)\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        def dfs(s, node, u, cnt):\n",
    "            if node.is_end and u == len(s) and cnt == 1:\n",
    "                return True \n",
    "            \n",
    "            if cnt > 1 or u == len(s):\n",
    "                return False\n",
    "            \n",
    "            for c in node.son.keys():\n",
    "                if dfs(s, node.son[c], u + 1, cnt + (s[u] != c)):\n",
    "                    return True \n",
    "            return False\n",
    "        \n",
    "        return dfs(searchWord, self.root, 0, 0)\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TrieNode:\n",
    "    def __init__(self, length=-1):        \n",
    "        self.length = length        \n",
    "        self.children = {}\n",
    "        self.d = None\n",
    "\n",
    "        return\n",
    "\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.root = TrieNode()\n",
    "\n",
    "        return\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        \"\"\"        \n",
    "        node = self.root\n",
    "        for char in word:\n",
    "            if char not in node.children:\n",
    "                node.children[char] = TrieNode()\n",
    "            node = node.children[char]\n",
    "            node.d = char\n",
    "        node.length = len(word)        \n",
    "        \n",
    "        return    \n",
    "    \n",
    "   \n",
    "    def search(self, point, length, errCnt, word) -> bool:\n",
    "        stack = [[self.root, 0, 0, 0]]        \n",
    "        while len(stack) != 0 and point < len(word):            \n",
    "            node, e, d, p = stack.pop(-1)\n",
    "\n",
    "            if node.length == len(word) and e == 1:\n",
    "                return True\n",
    "\n",
    "            if e > 1 or p == len(word):\n",
    "                continue\n",
    "            \n",
    "            for key, value in node.children.items():                  \n",
    "                if key == word[p]:\n",
    "                    stack.append([value, e, d+1, p+1])\n",
    "                else:\n",
    "                    stack.append([value, e+1, d+1, p+1])\n",
    "           \n",
    "              \n",
    "        return False\n",
    "\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.__trieObj = Trie()\n",
    "\n",
    "        return\n",
    "\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for word in dictionary:\n",
    "            self.__trieObj.insert(word)\n",
    "        \n",
    "        return\n",
    "\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "      \n",
    "        return self.__trieObj.search(0, len(searchWord), 0, searchWord)\n",
    "\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TrieNode:\n",
    "    __slots__ = 'ch', 'children', 'is_word'\n",
    "    def __init__(self, ch=0):\n",
    "        self.ch = ch\n",
    "        self.children = dict()\n",
    "        self.is_word = False\n",
    "\n",
    "def insert(root, word):\n",
    "    n = root\n",
    "    for c in word:\n",
    "        if c in n.children:\n",
    "            n = n.children[c]\n",
    "        else:\n",
    "            n.children[c] = TrieNode(c)\n",
    "            n = n.children[c]\n",
    "    n.is_word = True\n",
    "\n",
    "def searchTN(node, word, i, k):\n",
    "    if i == len(word) - 1:\n",
    "        if node.ch == word[i] and node.is_word:\n",
    "            return k == 0\n",
    "        elif node.is_word:\n",
    "            return k == 1\n",
    "        else:\n",
    "            return False\n",
    "    if node.ch != word[i]:\n",
    "        k -= 1\n",
    "    if k < 0: return False\n",
    "    for chd in node.children.values():\n",
    "        if searchTN(chd, word, i + 1, k):\n",
    "            return True\n",
    "    return False\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = TrieNode()\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for w in dictionary:\n",
    "            insert(self.root, w)\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        for node in self.root.children.values():\n",
    "            if searchTN(node, word, 0, 1):\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.virtuals = collections.defaultdict(set)\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for word in dictionary:\n",
    "            for i in range(len(word)):\n",
    "                self.virtuals[word[:i] + \"*\" + word[i+1:]].add(word)\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        for i in range(len(searchWord)):\n",
    "            virtual = searchWord[:i] + \"*\" + searchWord[i+1:]\n",
    "            if virtual in self.virtuals and (searchWord not in self.virtuals[virtual] or len(self.virtuals[virtual]) > 1):\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "\n",
    "    def insert(self, word):\n",
    "        cur = self.root\n",
    "        for ch in word:\n",
    "            idx = ord(ch) - ord('a')\n",
    "            if cur.children[idx] is None:\n",
    "                cur.children[idx] = Node()\n",
    "            cur = cur.children[idx]\n",
    "        cur.end = True\n",
    "\n",
    "    def search(self, target):\n",
    "        n = len(target)\n",
    "        def dfs(node, i, diff):\n",
    "            if not node:\n",
    "                return False\n",
    "            if i == n:\n",
    "                return diff\n",
    "            if diff:\n",
    "                return dfs(node.children[ord(target[i]) - ord('a')], i + 1, diff)\n",
    "            else:\n",
    "                for idx in range(26):\n",
    "                    if dfs(node.children[idx], i + 1, idx != ord(target[i]) - ord('a')):\n",
    "                        return True\n",
    "            return False\n",
    "        return dfs(self.root, 0, False)\n",
    "\n",
    "class Node:\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 26\n",
    "        self.end = False\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Tire:\n",
    "    def __init__(self):\n",
    "        self.children = dict()\n",
    "        self.isEnd = False\n",
    "\n",
    "    def insert(self, word) -> None:\n",
    "        cur = self\n",
    "        for ch in word:\n",
    "            if ch not in cur.children:\n",
    "                cur.children[ch] = Tire()\n",
    "            cur = cur.children[ch]\n",
    "        cur.isEnd = True\n",
    "\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        cur = self\n",
    "        for ch in searchWord:\n",
    "            if ch not in cur.children:\n",
    "                return False\n",
    "            cur = cur.children[ch]\n",
    "        return cur is not None and cur.isEnd\n",
    "\n",
    "class MagicDictionary:\n",
    "    def __init__(self):\n",
    "        self.tire_tree = Tire()\n",
    "    \n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for word in dictionary:\n",
    "            self.tire_tree.insert(word)\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        size = len(searchWord)\n",
    "        for i in range(size):\n",
    "            for j in range(26):\n",
    "                new_ch = chr(ord('a') + j)\n",
    "                if new_ch != searchWord[i]:\n",
    "                    new_word = searchWord[:i] + new_ch + searchWord[i+1:]\n",
    "                    if self.tire_tree.search(new_word):\n",
    "                        return True\n",
    "        return False\n",
    "\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.child = collections.defaultdict(Trie)\n",
    "        self.isend = False\n",
    "    def insert(self, word):\n",
    "        cur = self\n",
    "        for ch in word:\n",
    "            if ch not in cur.child:\n",
    "                cur.child[ch] = Trie()\n",
    "            cur = cur.child[ch]\n",
    "        cur.isend = True\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = Trie()\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for word in dictionary:\n",
    "            cur = self.root\n",
    "            cur.insert(word)\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        def dfs(node, pos, change):\n",
    "            if pos == len(searchWord):\n",
    "                return change and node.isend \n",
    "            ch = searchWord[pos]\n",
    "            if ch in node.child:\n",
    "                if dfs(node.child[ch], pos + 1, change):\n",
    "                    return True \n",
    "            if not change:\n",
    "                for nex in node.child:\n",
    "                    if nex != ch:\n",
    "                        if dfs(node.child[nex], pos + 1, True):\n",
    "                            return True \n",
    "            return False \n",
    "        cur= self.root \n",
    "        return dfs(cur, 0, False)\n",
    "            \n",
    "\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 26\n",
    "        self.isEnd = False\n",
    "\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for word in dictionary:\n",
    "            self.insert(word)\n",
    "\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        def helper(root, word):\n",
    "            pos = root\n",
    "            for ch in word:\n",
    "                chId = ord(ch) - ord('a')\n",
    "                if not pos.children[chId]:\n",
    "                    return False\n",
    "                pos = pos.children[chId]\n",
    "            return pos.isEnd\n",
    "\n",
    "        cur = self\n",
    "        for i, ch in enumerate(searchWord):\n",
    "            chId = ord(ch) - ord('a')\n",
    "            for id, child in enumerate(cur.children):\n",
    "                if not child or child == cur.children[chId]:\n",
    "                    continue\n",
    "                if helper(child, searchWord[i+1:]):\n",
    "                    return True\n",
    "            if not cur.children[chId]:\n",
    "                return False\n",
    "            cur = cur.children[chId]\n",
    "        return False\n",
    "\n",
    "    def insert(self, word):\n",
    "        cur = self\n",
    "        for ch in word:\n",
    "            chId = ord(ch) - ord('a')\n",
    "            if not cur.children[chId]:\n",
    "                cur.children[chId] = MagicDictionary()\n",
    "            cur = cur.children[chId]\n",
    "        cur.isEnd = True\n",
    "\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.trie = Trie()\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for word in dictionary:\n",
    "            self.trie.insert(word)\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        return self.trie.dfs(searchWord, 0, 0)\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 26\n",
    "        self.isEnd = False\n",
    "\n",
    "    def insert(self, word):\n",
    "        node = self\n",
    "        for ch in word:\n",
    "            ch = ord(ch) - ord('a')\n",
    "            if not node.children[ch]:\n",
    "                node.children[ch] = Trie()\n",
    "            node = node.children[ch]\n",
    "        node.isEnd = True\n",
    "        \n",
    "    def dfs(self, word, cur, replaced):\n",
    "        node = self\n",
    "        if node.isEnd and cur == len(word) and replaced == 1:\n",
    "            return True\n",
    "        if not node or cur >= len(word) or replaced >= 2:\n",
    "            return False\n",
    "        \n",
    "        ch = ord(word[cur]) - ord('a')\n",
    "        branches = False\n",
    "        for i, child in enumerate(node.children):\n",
    "            if not child: continue    \n",
    "            if child.dfs(word, cur + 1, replaced + int(i != ch)):\n",
    "                return True\n",
    "        return branches\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TrieNode:\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 26\n",
    "        self.isEnd = False\n",
    "\n",
    "    def insert(self, word):\n",
    "        node = self\n",
    "        for ch in word:\n",
    "            if not node.children[ord(ch) - ord('a')]: node.children[ord(ch) - ord('a')] = TrieNode()\n",
    "            node = node.children[ord(ch) - ord('a')]\n",
    "        node.isEnd = True\n",
    "\n",
    "class MagicDictionary:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.trieRoot = TrieNode()\n",
    "\n",
    "    def buildDict(self, dictionary: List[str]) -> None:\n",
    "        for word in dictionary:\n",
    "            self.trieRoot.insert(word)\n",
    "\n",
    "    def search(self, searchWord: str) -> bool:\n",
    "        def dfs(idx, change, node):\n",
    "            # print(idx)\n",
    "            if idx == len(searchWord):\n",
    "                if node.isEnd and change == 1: return True\n",
    "                else: return False\n",
    "            if change == 1 and node.children[ord(searchWord[idx]) - ord('a')]: return dfs(idx + 1, change, node.children[ord(searchWord[idx]) - ord('a')])\n",
    "            elif change == 0:\n",
    "                ret = False\n",
    "                for i in range(26):\n",
    "                    if i == ord(searchWord[idx]) - ord('a') and node.children[i]: ret = ret or dfs(idx + 1, change, node.children[i])\n",
    "                    elif node.children[i]: ret = ret or dfs(idx + 1, change + 1, node.children[i])\n",
    "                return ret\n",
    "            return False\n",
    "\n",
    "        return dfs(0, 0, self.trieRoot)\n",
    "\n",
    "\n",
    "# Your MagicDictionary object will be instantiated and called as such:\n",
    "# obj = MagicDictionary()\n",
    "# obj.buildDict(dictionary)\n",
    "# param_2 = obj.search(searchWord)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class MyQueue:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.queue = []\n",
    "\n",
    "\n",
    "    def push(self, x: int) -> None:\n",
    "        \"\"\"\n",
    "        Push element x to the back of queue.\n",
    "        \"\"\"\n",
    "        self.queue.insert(0,x)\n",
    "\n",
    "\n",
    "    def pop(self) -> int:\n",
    "        \"\"\"\n",
    "        Removes the element from in front of queue and returns that element.\n",
    "        \"\"\"\n",
    "        return self.queue.pop()\n",
    "\n",
    "\n",
    "    def peek(self) -> int:\n",
    "        \"\"\"\n",
    "        Get the front element.\n",
    "        \"\"\"\n",
    "        if not self.queue:\n",
    "            return None\n",
    "        else:\n",
    "            return self.queue[-1]\n",
    "\n",
    "\n",
    "\n",
    "    def empty(self) -> bool:\n",
    "        \"\"\"\n",
    "        Returns whether the queue is empty.\n",
    "        \"\"\"\n",
    "        return len(self.queue) == 0\n",
    "\n",
    "\n",
    "\n",
    "# Your MyQueue object will be instantiated and called as such:\n",
    "# obj = MyQueue()\n",
    "# obj.push(x)\n",
    "# param_2 = obj.pop()\n",
    "# param_3 = obj.peek()\n",
    "# param_4 = obj.empty()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class MyQueue:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.stack=[]\n",
    "\n",
    "    def push(self, x: int) -> None:\n",
    "        \"\"\"\n",
    "        Push element x to the back of queue.\n",
    "        \"\"\"\n",
    "        self.stack.insert(0,x)\n",
    "\n",
    "    def pop(self) -> int:\n",
    "        \"\"\"\n",
    "        Removes the element from in front of queue and returns that element.\n",
    "        \"\"\"\n",
    "        return self.stack.pop()\n",
    "\n",
    "    def peek(self) -> int:\n",
    "        \"\"\"\n",
    "        Get the front element.\n",
    "        \"\"\"\n",
    "        return self.stack[-1]\n",
    "\n",
    "    def empty(self) -> bool:\n",
    "        \"\"\"\n",
    "        Returns whether the queue is empty.\n",
    "        \"\"\"\n",
    "        return len(self.stack) ==0\n",
    "\n",
    "\n",
    "# Your MyQueue object will be instantiated and called as such:\n",
    "# obj = MyQueue()\n",
    "# obj.push(x)\n",
    "# param_2 = obj.pop()\n",
    "# param_3 = obj.peek()\n",
    "# param_4 = obj.empty()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class MyQueue:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.que = list()\n",
    "\n",
    "    def push(self, x: int) -> None:\n",
    "        self.que.insert(0, x)\n",
    "\n",
    "    def pop(self) -> int:\n",
    "        return self.que.pop()\n",
    "\n",
    "    def peek(self) -> int:\n",
    "        return self.que[-1]\n",
    "\n",
    "    def empty(self) -> bool:\n",
    "        return self.que == []\n",
    "\n",
    "\n",
    "# Your MyQueue object will be instantiated and called as such:\n",
    "# obj = MyQueue()\n",
    "# obj.push(x)\n",
    "# param_2 = obj.pop()\n",
    "# param_3 = obj.peek()\n",
    "# param_4 = obj.empty()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class MyStack:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.queue=[]\n",
    "\n",
    "    def push(self, x):\n",
    "        \"\"\"\n",
    "        Push element x onto stack.\n",
    "        :type x: int\n",
    "        :rtype: void\n",
    "        \"\"\"\n",
    "        self.queue.insert(0,x)\n",
    "        for i in range(0,len(self.queue)-1):\n",
    "            self.queue.insert(0,self.queue[-1])\n",
    "            self.queue.pop()\n",
    "\n",
    "    def pop(self):\n",
    "        \"\"\"\n",
    "        Removes the element on top of the stack and returns that element.\n",
    "        :rtype: int\n",
    "        \"\"\"\n",
    "        return self.queue.pop()\n",
    "\n",
    "    def top(self):\n",
    "        \"\"\"\n",
    "        Get the top element.\n",
    "        :rtype: int\n",
    "        \"\"\"\n",
    "        return self.queue[-1]\n",
    "\n",
    "    def empty(self):\n",
    "        \"\"\"\n",
    "        Returns whether the stack is empty.\n",
    "        :rtype: bool\n",
    "        \"\"\"\n",
    "        return len(self.queue)==0\n",
    "\n",
    "\n",
    "# Your MyStack object will be instantiated and called as such:\n",
    "# obj = MyStack()\n",
    "# obj.push(x)\n",
    "# param_2 = obj.pop()\n",
    "# param_3 = obj.top()\n",
    "# param_4 = obj.empty()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = {'#': 0, '$': 0}\n",
    "    \n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self.root\n",
    "        for c in word:\n",
    "            if c not in node:\n",
    "                node[c] = {'#': 0, '$': 0}\n",
    "            node['#'] += 1\n",
    "            node = node[c]\n",
    "        node['#'] += 1\n",
    "        node['$'] += 1\n",
    "            \n",
    "        \n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self.root\n",
    "        for c in word:\n",
    "            if c not in node:\n",
    "                return 0\n",
    "            else:\n",
    "                node = node[c]\n",
    "        return node['$']\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self.root\n",
    "        for c in prefix:\n",
    "            if c not in node:\n",
    "                return 0\n",
    "            else:\n",
    "                node = node[c]\n",
    "        return node['#']\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        node = self.root\n",
    "        for c in word:\n",
    "            node['#'] -= 1\n",
    "            if c not in node:\n",
    "                return\n",
    "            else:\n",
    "                node = node[c]\n",
    "        node['#'] -= 1\n",
    "        node['$'] -= 1\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.m1 = defaultdict(int)\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.m1[word] += 1\n",
    "\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        return self.m1[word]\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        cnt = 0\n",
    "        for i in self.m1:\n",
    "            if i.startswith(prefix):\n",
    "                cnt += self.m1[i]\n",
    "        return cnt\n",
    "\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        self.m1[word] -= 1\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = {}\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        p = self.root\n",
    "        for w in word:\n",
    "            if w not in p:\n",
    "                p[w] = {}\n",
    "            p = p[w]\n",
    "            if 0 in p:\n",
    "                p[0] += 1\n",
    "            else:\n",
    "                p[0] = 1\n",
    "        if 1 in p:\n",
    "            p[1] += 1\n",
    "        else:\n",
    "            p[1] = 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        p = self.root\n",
    "        for w in word:\n",
    "            if w not in p:\n",
    "                return 0\n",
    "            p = p[w]\n",
    "        return p[1] if 1 in p else 0\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        p = self.root\n",
    "        for w in prefix:\n",
    "            if w not in p:\n",
    "                return 0\n",
    "            p = p[w]\n",
    "        return p[0] if 0 in p else 0 \n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        p = self.root\n",
    "        for w in word:\n",
    "            if p[w][0] == 1:\n",
    "                p.pop(w)\n",
    "                return\n",
    "            else:\n",
    "                p[w][0] -= 1\n",
    "                p = p[w]\n",
    "        # p[0] -= 1\n",
    "        p[1] -= 1\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "      self.dict = {}\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "      record = self.dict\n",
    "      for c in word:\n",
    "        if c not in record:\n",
    "          record[c] = {}\n",
    "        record = record[c]\n",
    "      if 'count' in record:\n",
    "        record['count'] += 1\n",
    "      else:\n",
    "        record['count'] = 1\n",
    "\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "      record = self.dict\n",
    "      for c in word:\n",
    "        if c not in record:\n",
    "          return 0\n",
    "        record = record[c]\n",
    "      if 'count' not in record:\n",
    "        return 0\n",
    "      return record['count']\n",
    "\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "      res = 0\n",
    "      record = self.dict\n",
    "      for c in prefix:\n",
    "        if c not in record:\n",
    "          return 0\n",
    "        record = record[c]\n",
    "      # print(record)\n",
    "      def dfs(record):\n",
    "        for key in record:\n",
    "          if key == 'count':\n",
    "            nonlocal res\n",
    "            res += record['count']\n",
    "          else:\n",
    "            dfs(record[key])\n",
    "      dfs(record)\n",
    "      return res\n",
    "\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "      record = self.dict\n",
    "      for c in word:\n",
    "        record = record[c]\n",
    "      record['count'] -= 1\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from typing import Generator, Iterable, Optional, Tuple\n",
    "\n",
    "\n",
    "class TrieNode:\n",
    "    __slots__ = (\"wordCount\", \"preCount\", \"children\")\n",
    "\n",
    "    def __init__(self):\n",
    "        self.wordCount = 0\n",
    "        self.preCount = 0\n",
    "        self.children = dict()\n",
    "\n",
    "\n",
    "class Trie2:\n",
    "    __slots__ = \"root\"\n",
    "\n",
    "    def __init__(self, words: Optional[Iterable[str]] = None):\n",
    "        self.root = TrieNode()\n",
    "        for word in words or ():\n",
    "            self.insert(word)\n",
    "\n",
    "    def insert(self, s: str) -> None:\n",
    "        if not s:\n",
    "            return\n",
    "        node = self.root\n",
    "        for char in s:\n",
    "            if char not in node.children:\n",
    "                newNode = TrieNode()\n",
    "                node.children[char] = newNode\n",
    "                node = newNode\n",
    "            else:\n",
    "                node = node.children[char]\n",
    "            node.preCount += 1\n",
    "        node.wordCount += 1\n",
    "\n",
    "    def remove(self, s: str) -> None:\n",
    "        \"\"\"从前缀树中移除`1个`s 需要保证s在前缀树中\"\"\"\n",
    "        if not s:\n",
    "            return\n",
    "        node = self.root\n",
    "        for char in s:\n",
    "            node = node.children[char]\n",
    "            node.preCount -= 1\n",
    "        node.wordCount -= 1\n",
    "\n",
    "    def enumerate(self, s: str) -> Generator[Tuple[int, TrieNode], None, None]:\n",
    "        if not s:\n",
    "            return\n",
    "        node = self.root\n",
    "        for i, char in enumerate(s):\n",
    "            if char not in node.children:\n",
    "                return\n",
    "            node = node.children[char]\n",
    "            yield i, node\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "\n",
    "    class Trie:\n",
    "        def __init__(self):\n",
    "            self.trie = Trie2()\n",
    "\n",
    "        def insert(self, word: str) -> None:\n",
    "            self.trie.insert(word)\n",
    "\n",
    "        def countWordsEqualTo(self, word: str) -> int:\n",
    "            for i, node in self.trie.enumerate(word):\n",
    "                if i == len(word) - 1:\n",
    "                    return node.wordCount\n",
    "            return 0\n",
    "\n",
    "        def countWordsStartingWith(self, prefix: str) -> int:\n",
    "            for i, node in self.trie.enumerate(prefix):\n",
    "                if i == len(prefix) - 1:\n",
    "                    return node.preCount\n",
    "            return 0\n",
    "\n",
    "        def erase(self, word: str) -> None:\n",
    "            self.trie.remove(word)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self):\n",
    "      self.cnt = 0\n",
    "      self.end = 0\n",
    "      self.nexts = dict()\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self.root\n",
    "        node.cnt += 1\n",
    "        for x in word:\n",
    "            if x not in node.nexts:\n",
    "                node.nexts[x] = Node()\n",
    "            node = node.nexts[x]\n",
    "            node.cnt += 1\n",
    "        node.end += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self.root\n",
    "        for x in word:\n",
    "            if x not in node.nexts:\n",
    "                return 0\n",
    "            node = node.nexts[x]\n",
    "        return node.end\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self.root\n",
    "        for x in prefix:\n",
    "            if x not in node.nexts:\n",
    "                return 0\n",
    "            node = node.nexts[x]\n",
    "        return node.cnt\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        node = self.root\n",
    "        node.cnt -= 1\n",
    "        for x in word:\n",
    "            if x not in node.nexts:\n",
    "                node.nexts[x] = Node()\n",
    "            node = node.nexts[x]\n",
    "            node.cnt -= 1\n",
    "        node.end -= 1\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TreeNode:\n",
    "    def __init__(self):\n",
    "        self.p = 0\n",
    "        self.e = 0\n",
    "        self.nexts = {}\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = TreeNode()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.root.p += 1\n",
    "        node = self.root\n",
    "        for i in word:\n",
    "            if i not in node.nexts.keys():\n",
    "                node.nexts[i] = TreeNode()\n",
    "            node.nexts[i].p += 1\n",
    "            node = node.nexts[i]\n",
    "        node.e += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self.root\n",
    "        for i in word:\n",
    "            if i in node.nexts.keys():\n",
    "                node = node.nexts[i]\n",
    "            else:\n",
    "                return 0\n",
    "        return node.e\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self.root\n",
    "        for i in prefix:\n",
    "            if i in node.nexts.keys():\n",
    "                node = node.nexts[i]\n",
    "            else:\n",
    "                return 0\n",
    "        return node.p\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        if self.countWordsEqualTo(word) > 0:\n",
    "            node = self.root\n",
    "            node.p -= 1\n",
    "            for i in word:\n",
    "                node.nexts[i].p -= 1\n",
    "                if node.nexts[i].p == 0:\n",
    "                    del node.nexts[i]\n",
    "                    return\n",
    "                else:\n",
    "                    node = node.nexts[i]\n",
    "            node.e -= 1\n",
    "            \n",
    "        \n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TrieNode:\n",
    "    def __init__(self):\n",
    "        self.p = 0\n",
    "        self.e = 0\n",
    "        self.nexts = {}\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = TrieNode()\n",
    "        \n",
    "    def insert(self, word: str) -> None:\n",
    "        word_list = list(word)\n",
    "        node = self.root\n",
    "        node.p += 1\n",
    "        for c in word_list:\n",
    "            if c not in node.nexts:\n",
    "                node.nexts[c] = TrieNode()\n",
    "            node = node.nexts[c]\n",
    "            node.p += 1\n",
    "        node.e += 1\n",
    "\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        word_list = list(word)\n",
    "        node = self.root\n",
    "        for c in word_list:\n",
    "            if c not in node.nexts:\n",
    "                return 0\n",
    "            node = node.nexts[c]\n",
    "        return node.e\n",
    "\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        word_list = list(prefix)\n",
    "        node = self.root\n",
    "        for c in word_list:\n",
    "            if c not in node.nexts:\n",
    "                return 0\n",
    "            node = node.nexts[c]\n",
    "        return node.p\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        if self.countWordsEqualTo(word) == 0:\n",
    "            return\n",
    "        word_list = list(word)\n",
    "        node = self.root\n",
    "        node.p -= 1\n",
    "        for c in word_list:\n",
    "            if node.nexts[c].p - 1 == 0:\n",
    "                del node.nexts[c]\n",
    "                return\n",
    "            node = node.nexts[c]\n",
    "            node.p -= 1\n",
    "        node.e -=1\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children=dict()\n",
    "        self.start=0\n",
    "        self.end=0\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        root=self\n",
    "        for c in word:\n",
    "            if c not in root.children:\n",
    "                root.children[c]=Trie()\n",
    "            root=root.children[c]\n",
    "            root.start+=1\n",
    "        root.end+=1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        root=self\n",
    "        for c in word:\n",
    "            if c not in root.children:\n",
    "                return 0\n",
    "            root=root.children[c]\n",
    "        return root.end\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        root=self\n",
    "        for c in prefix:\n",
    "            if c not in root.children:\n",
    "                return 0\n",
    "            root=root.children[c]\n",
    "        return root.start\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        root=self\n",
    "        for c in word:\n",
    "            root=root.children[c]\n",
    "            if root.start>0:\n",
    "                root.start-=1\n",
    "        if root.end>0:\n",
    "            root.end-=1\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TreeNode:\n",
    "    def __init__(self):\n",
    "        self.children={}\n",
    "        self.is_word=0\n",
    "        self.as_word=0\n",
    "        self.as_prefix=0\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.root=TreeNode()\n",
    "    def insert(self, word: str) -> None:\n",
    "        node=self.root\n",
    "        for ch in word:\n",
    "            if ch not in node.children:\n",
    "                node.children[ch]=TreeNode()\n",
    "            node.children[ch].as_prefix+=1\n",
    "            node=node.children[ch]\n",
    "        node.is_word=True\n",
    "        node.as_word+=1\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node=self.root\n",
    "        for ch in word:\n",
    "            if ch not in node.children:return 0\n",
    "            else:node=node.children[ch]\n",
    "        return node.as_word\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node=self.root\n",
    "        for ch in prefix:\n",
    "            if ch not in node.children:return 0\n",
    "            else:node=node.children[ch]\n",
    "        return node.as_prefix\n",
    "    def erase(self, word: str) -> None:#删除一个单词\n",
    "        node=self.root\n",
    "        for ch in word:\n",
    "            if ch not in node.children:return \n",
    "            else:\n",
    "                node.children[ch].as_prefix-=1\n",
    "                node=node.children[ch]\n",
    "        node.as_word-=1\n",
    "        if node.as_word==0:node.is_word=False\n",
    "    def searchPrefix(self,word):\n",
    "        node=self.root\n",
    "        for ch in word:\n",
    "            if ch not in node.children:return None\n",
    "            node=node.children[ch]\n",
    "        return node \n",
    "    def search(self,word):\n",
    "        node=self.searchPrefix(word)\n",
    "        if node and node.is_word:return True\n",
    "        else:return False\n",
    "    def startsWith(self,word):\n",
    "        node=self.searchPrefix(word)\n",
    "        return True if node else False\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.visits = 0\n",
    "        self.ends = 0\n",
    "        self.children = defaultdict(Trie)\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        cur = self\n",
    "        for c in word:\n",
    "            cur = cur.children[c]\n",
    "            cur.visits += 1\n",
    "        cur.ends += 1\n",
    "\n",
    "\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        cur = self \n",
    "        for c in word:\n",
    "            if c in cur.children:\n",
    "                cur = cur.children[c]\n",
    "            else:\n",
    "                return 0\n",
    "        return cur.ends\n",
    "\n",
    "\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        cur = self \n",
    "        for c in prefix:\n",
    "            if c in cur.children:\n",
    "                cur = cur.children[c]\n",
    "            else:\n",
    "                return 0\n",
    "        return cur.visits\n",
    "\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        cur = self \n",
    "        for c in word:\n",
    "            cur = cur.children[c]\n",
    "            cur.visits -= 1\n",
    "        cur.ends -= 1\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = {}\n",
    "        self.prefixCount = 0\n",
    "        self.endCount = 0\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self\n",
    "        for ch in word:\n",
    "            if node.children.get(ch) is None:\n",
    "                node.children[ch] = Trie()\n",
    "            node = node.children[ch]\n",
    "            node.prefixCount += 1\n",
    "        node.endCount += 1\n",
    "\n",
    "    def searchPrefix(self, prefix: str) -> \"Trie\":\n",
    "        node = self\n",
    "        for ch in prefix:\n",
    "            if node.children.get(ch) is None:\n",
    "                return None\n",
    "            node = node.children[ch]\n",
    "        return node\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self.searchPrefix(word)\n",
    "        return 0 if node is None else node.endCount\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self.searchPrefix(prefix)\n",
    "        return 0 if node is None else node.prefixCount\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        # if self.countWordsEqualTo(word) == 0:\n",
    "        #    return\n",
    "        node = self\n",
    "        for ch in word:\n",
    "            parent = node\n",
    "            node = node.children[ch]\n",
    "            node.prefixCount -= 1\n",
    "            if node.prefixCount == 0:\n",
    "                parent.children[ch] = None\n",
    "                return\n",
    "        node.endCount -= 1\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.children = dict()\n",
    "        self.as_prefix = 0      #插入word时，每一个w结点+1\n",
    "        self.as_word = 0        #插入word结束时，统计一下\n",
    "\n",
    "    #### 插入一个单词word\n",
    "    def insert(self, word: str) -> None:\n",
    "        rt = self\n",
    "        for w in word:\n",
    "            if w not in rt.children:    #可以用defaultdict(Trie())省心，但是这种写法思路更清晰\n",
    "                rt.children[w] = Trie()\n",
    "            rt.children[w].as_prefix += 1\n",
    "            rt = rt.children[w]\n",
    "        rt.as_word += 1\n",
    "\n",
    "    #### 统计word的个数\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        rt = self\n",
    "        for w in word:\n",
    "            if w not in rt.children:\n",
    "                return 0\n",
    "            else:\n",
    "                rt = rt.children[w]\n",
    "        return rt.as_word\n",
    "\n",
    "    #### 统计前缀prefix的个数\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        rt = self\n",
    "        for p in prefix:\n",
    "            if p not in rt.children:\n",
    "                return 0\n",
    "            else:\n",
    "                rt = rt.children[p]\n",
    "        return rt.as_prefix\n",
    "\n",
    "    #### 只擦除一个word\n",
    "    def erase(self, word: str) -> None:\n",
    "        rt = self\n",
    "        for w in word:\n",
    "            if w not in rt.children:\n",
    "                return\n",
    "            else:\n",
    "                rt.children[w].as_prefix -= 1\n",
    "                rt = rt.children[w]\n",
    "        rt.as_word -= 1\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from typing import Generator, Iterable, Optional, Tuple\n",
    "\n",
    "\n",
    "class TrieNode:\n",
    "  \n",
    "\n",
    "    def __init__(self):\n",
    "        self.wordCount = 0\n",
    "        self.preCount = 0\n",
    "        self.children = dict()\n",
    "\n",
    "\n",
    "class Trie2:\n",
    "    __slots__ = \"root\"\n",
    "\n",
    "    def __init__(self, words: Optional[Iterable[str]] = None):\n",
    "        self.root = TrieNode()\n",
    "        for word in words or ():\n",
    "            self.insert(word)\n",
    "\n",
    "    def insert(self, s: str) -> None:\n",
    "        if not s:\n",
    "            return\n",
    "        node = self.root\n",
    "        for char in s:\n",
    "            if char not in node.children:\n",
    "                newNode = TrieNode()\n",
    "                node.children[char] = newNode\n",
    "                node = newNode\n",
    "            else:\n",
    "                node = node.children[char]\n",
    "            node.preCount += 1\n",
    "        node.wordCount += 1\n",
    "\n",
    "    def remove(self, s: str) -> None:\n",
    "        \"\"\"从前缀树中移除`1个`s 需要保证s在前缀树中\"\"\"\n",
    "        if not s:\n",
    "            return\n",
    "        node = self.root\n",
    "        for char in s:\n",
    "            node = node.children[char]\n",
    "            node.preCount -= 1\n",
    "        node.wordCount -= 1\n",
    "\n",
    "    def enumerate(self, s: str) -> Generator[Tuple[int, TrieNode], None, None]:\n",
    "        if not s:\n",
    "            return\n",
    "        node = self.root\n",
    "        for i, char in enumerate(s):\n",
    "            if char not in node.children:\n",
    "                return\n",
    "            node = node.children[char]\n",
    "            yield i, node\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "\n",
    "    class Trie:\n",
    "        def __init__(self):\n",
    "            self.trie = Trie2()\n",
    "\n",
    "        def insert(self, word: str) -> None:\n",
    "            self.trie.insert(word)\n",
    "\n",
    "        def countWordsEqualTo(self, word: str) -> int:\n",
    "            for i, node in self.trie.enumerate(word):\n",
    "                if i == len(word) - 1:\n",
    "                    return node.wordCount\n",
    "            return 0\n",
    "\n",
    "        def countWordsStartingWith(self, prefix: str) -> int:\n",
    "            for i, node in self.trie.enumerate(prefix):\n",
    "                if i == len(prefix) - 1:\n",
    "                    return node.preCount\n",
    "            return 0\n",
    "\n",
    "        def erase(self, word: str) -> None:\n",
    "            self.trie.remove(word)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.children = dict()\n",
    "        self.as_prefix = 0      #插入word时，每一个w结点+1\n",
    "        self.as_word = 0        #插入word结束时，统计一下\n",
    "\n",
    "    #### 插入一个单词word\n",
    "    def insert(self, word: str) -> None:\n",
    "        rt = self\n",
    "        for w in word:\n",
    "            if w not in rt.children:    #可以用defaultdict(Trie())省心，但是这种写法思路更清晰\n",
    "                rt.children[w] = Trie()\n",
    "            rt.children[w].as_prefix += 1\n",
    "            rt = rt.children[w]\n",
    "        rt.as_word += 1\n",
    "\n",
    "    #### 统计word的个数\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        rt = self\n",
    "        for w in word:\n",
    "            if w not in rt.children:\n",
    "                return 0\n",
    "            else:\n",
    "                rt = rt.children[w]\n",
    "        return rt.as_word\n",
    "\n",
    "    #### 统计前缀prefix的个数\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        rt = self\n",
    "        for p in prefix:\n",
    "            if p not in rt.children:\n",
    "                return 0\n",
    "            else:\n",
    "                rt = rt.children[p]\n",
    "        return rt.as_prefix\n",
    "\n",
    "    #### 只擦除一个word\n",
    "    def erase(self, word: str) -> None:\n",
    "        rt = self\n",
    "        for w in word:\n",
    "            if w not in rt.children:\n",
    "                return\n",
    "            else:\n",
    "                rt.children[w].as_prefix -= 1\n",
    "                rt = rt.children[w]\n",
    "        rt.as_word -= 1\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = defaultdict(Trie)\n",
    "        ## 记录添加了多少次该单词\n",
    "        self.word_count = 0\n",
    "        ## 记录在这条路径后面，有多少个单词\n",
    "        self.pre_count = 0\n",
    "        \n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        cur = self\n",
    "        for ch in word:\n",
    "            \n",
    "            cur = cur.children[ch]\n",
    "            cur.pre_count += 1\n",
    "        cur.word_count+=1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        cur = self\n",
    "        for ch in word:\n",
    "            cur = cur.children[ch]\n",
    "        return cur.word_count\n",
    "\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        cur = self\n",
    "        for ch in prefix:\n",
    "            cur = cur.children[ch]\n",
    "        return cur.pre_count\n",
    "\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        cur = self\n",
    "        for ch in word:\n",
    "            cur = cur.children[ch]\n",
    "            cur.pre_count -= 1\n",
    "        cur.word_count -= 1\n",
    "\n",
    "        \n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.endCount = 0\n",
    "        self.count = 0\n",
    "        self.children = {}\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self\n",
    "        for c in word:\n",
    "            if c not in node.children:\n",
    "                node.children[c] = Trie()\n",
    "            node = node.children[c]\n",
    "            node.count += 1\n",
    "        node.endCount += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self._searchPrefix(word)\n",
    "        return node.endCount if node else 0\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self._searchPrefix(prefix)\n",
    "        return node.count if node else 0\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        node = self\n",
    "        for c in word:\n",
    "            node = node.children[c]\n",
    "            node.count -= 1\n",
    "        node.endCount -= 1\n",
    "\n",
    "    def _searchPrefix(self, prefix: str) -> 'Trie':\n",
    "        node = self\n",
    "        for c in prefix:\n",
    "            if c not in node.children:\n",
    "                return None\n",
    "            node = node.children[c]\n",
    "        return node\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TrieNode:\n",
    "    R = 26\n",
    "    def __init__(self, val=0):\n",
    "        self.val = val\n",
    "        self.children = [None] * self.R\n",
    "class Trie:\n",
    "    idxofs = ord('a')\n",
    "    R = 26\n",
    "    def __init__(self):\n",
    "        self.root = TrieNode()\n",
    "\n",
    "    def getNode(self, word: str) -> TrieNode:\n",
    "        p = self.root\n",
    "        for i in range(len(word)):\n",
    "            if p is None:\n",
    "                return\n",
    "            c = word[i]\n",
    "            p = p.children[ord(c)-self.idxofs]\n",
    "        return p\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        \n",
    "\n",
    "        def insertWord(node, w):\n",
    "            if w == \"\":\n",
    "                node.val += 1\n",
    "                return\n",
    "            c = w[0]\n",
    "            # print(ord(c)-self.idxofs)\n",
    "            child = node.children[ord(c)-self.idxofs]\n",
    "            if not child:\n",
    "                child = TrieNode()\n",
    "                node.children[ord(c)-self.idxofs] = child\n",
    "            insertWord(child, w[1:])\n",
    "\n",
    "        insertWord(self.root, word)\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        p = self.getNode(word)\n",
    "        return p.val if p else 0\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        p = self.getNode(prefix)\n",
    "        self.ans = 0\n",
    "        if not p:\n",
    "            return 0\n",
    "        def traverse(root):\n",
    "            if not root:\n",
    "                return\n",
    "            self.ans += root.val\n",
    "            for child in root.children:\n",
    "                if not child:\n",
    "                    continue\n",
    "                traverse(child)\n",
    "\n",
    "        traverse(p)\n",
    "        return self.ans\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        p = self.getNode(word)\n",
    "        if p and p.val > 0:\n",
    "            p.val -= 1\n",
    "        # else: return\n",
    "        \n",
    "        # if p.val == 0:\n",
    "        #     for i in range(len(word)-1, -1, -1):\n",
    "        #         for child in p.children:\n",
    "        #             if child:\n",
    "        #                 return\n",
    "        #         # parent = self.getNode(word[:i])\n",
    "        #         del child\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TreeNode:\n",
    "    def __init__(self):\n",
    "        self.p = 0\n",
    "        self.e = 0\n",
    "        self.nexts = [None] * 26\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = TreeNode()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.root.p += 1\n",
    "        node = self.root\n",
    "        for i in word:\n",
    "            pos = ord(i)-ord('a')\n",
    "            if node.nexts[pos] is None:\n",
    "                node.nexts[pos] = TreeNode()\n",
    "            node.nexts[pos].p += 1\n",
    "            node = node.nexts[pos]\n",
    "        node.e += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self.root\n",
    "        for i in word:\n",
    "            pos = ord(i) - ord('a')\n",
    "            if node.nexts[pos] is not None:\n",
    "                node = node.nexts[pos]\n",
    "            else:\n",
    "                return 0\n",
    "        return node.e\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self.root\n",
    "        for i in prefix:\n",
    "            pos = ord(i) - ord('a')\n",
    "            if node.nexts[pos] is not None:\n",
    "                node = node.nexts[pos]\n",
    "            else:\n",
    "                return 0\n",
    "        return node.p\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        node = self.root\n",
    "        node.p -= 1\n",
    "        for i in word:\n",
    "            pos = ord(i) - ord('a')\n",
    "            if node.nexts[pos] is not None:\n",
    "                node.nexts[pos].p -= 1\n",
    "                if node.nexts[pos].p == 0:\n",
    "                    node.nexts[pos] = None\n",
    "                    return\n",
    "                else:\n",
    "                    node = node.nexts[pos]\n",
    "            else:\n",
    "                return -1\n",
    "        node.e -= 1\n",
    "        \n",
    "        \n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TreeNode:\n",
    "    def __init__(self):\n",
    "        self.p = 0\n",
    "        self.e = 0\n",
    "        self.nexts = [None] * 26\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = TreeNode()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.root.p += 1\n",
    "        node = self.root\n",
    "        for i in word:\n",
    "            pos = ord(i)-ord('a')\n",
    "            if node.nexts[pos] is None:\n",
    "                node.nexts[pos] = TreeNode()\n",
    "            node.nexts[pos].p += 1\n",
    "            node = node.nexts[pos]\n",
    "        node.e += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self.root\n",
    "        for i in word:\n",
    "            pos = ord(i) - ord('a')\n",
    "            if node.nexts[pos] is not None:\n",
    "                node = node.nexts[pos]\n",
    "            else:\n",
    "                return 0\n",
    "        return node.e\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self.root\n",
    "        for i in prefix:\n",
    "            pos = ord(i) - ord('a')\n",
    "            if node.nexts[pos] is not None:\n",
    "                node = node.nexts[pos]\n",
    "            else:\n",
    "                return 0\n",
    "        return node.p\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        if self.countWordsEqualTo(word) > 0:\n",
    "            node = self.root\n",
    "            node.p -= 1\n",
    "            for i in word:\n",
    "                pos = ord(i) - ord('a')\n",
    "                node.nexts[pos].p -= 1\n",
    "                if node.nexts[pos].p == 0:\n",
    "                    node.nexts[pos] = None\n",
    "                    return\n",
    "                else:\n",
    "                    node = node.nexts[pos]\n",
    "            node.e -= 1\n",
    "            \n",
    "        \n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TrieNode:\n",
    "    def __init__(self):\n",
    "        self.isWord = False\n",
    "        self.next = {}\n",
    "        self.count = 0\n",
    "\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.root = TrieNode()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        curr = self.root\n",
    "        for w in word:\n",
    "            if w not in curr.next:\n",
    "                curr.next[w] = TrieNode()\n",
    "            curr = curr.next[w]\n",
    "        curr.isWord = True\n",
    "        curr.count += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        curr = self.root\n",
    "        for w in word:\n",
    "            if w not in curr.next:\n",
    "                return 0\n",
    "            curr = curr.next[w]\n",
    "        if curr.isWord:\n",
    "            return curr.count\n",
    "        return 0\n",
    "\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        curr = self.root\n",
    "        res = 0\n",
    "        for w in prefix:\n",
    "            if w not in curr.next:\n",
    "                return 0\n",
    "            curr = curr.next[w]\n",
    "        if curr.isWord:\n",
    "            res += curr.count\n",
    "        \n",
    "        def getCountFromNode(node):\n",
    "            res = 0\n",
    "            for w in node.next:\n",
    "                if node.next[w].isWord:\n",
    "                    res += node.next[w].count\n",
    "                res += getCountFromNode(node.next[w])\n",
    "            return res\n",
    "        \n",
    "        res += getCountFromNode(curr)\n",
    "        return res\n",
    "        \n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        curr = self.root\n",
    "        for w in word:\n",
    "            if w not in curr.next:\n",
    "                return\n",
    "            curr = curr.next[w]\n",
    "        \n",
    "        if curr.isWord and curr.count > 0:\n",
    "            curr.count -= 1\n",
    "            if curr.count == 0:\n",
    "                curr.isWord = False\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TrieNode:\n",
    "    def __init__(self):\n",
    "        self.prefix_cnt = 0\n",
    "        self.word_cnt = 0\n",
    "        self.children = [None for _ in range(26)]\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = TrieNode()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        p = self.root\n",
    "        for i in range(len(word)):\n",
    "            if not p.children[ord(word[i])-ord(\"a\")]:\n",
    "                p.children[ord(word[i])-ord(\"a\")] = TrieNode()\n",
    "            p = p.children[ord(word[i])-ord(\"a\")]\n",
    "            p.prefix_cnt += 1\n",
    "            if i == len(word)-1:\n",
    "                p.word_cnt += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        p = self.root\n",
    "        for i in range(len(word)):\n",
    "            if not p.children[ord(word[i])-ord(\"a\")]:\n",
    "                return 0\n",
    "            p = p.children[ord(word[i])-ord(\"a\")]\n",
    "            if i == len(word)-1:\n",
    "                return p.word_cnt\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        p = self.root\n",
    "        for i in range(len(prefix)):\n",
    "            if not p.children[ord(prefix[i])-ord(\"a\")]:\n",
    "                return 0\n",
    "            p = p.children[ord(prefix[i])-ord(\"a\")]\n",
    "            if i == len(prefix)-1:\n",
    "                return p.prefix_cnt\n",
    "\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        p = self.root\n",
    "        for i in range(len(word)):\n",
    "            p = p.children[ord(word[i])-ord(\"a\")]\n",
    "            p.prefix_cnt -= 1\n",
    "            if i == len(word)-1:\n",
    "                p.word_cnt -= 1\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.sons = [None for i in range(26)]\n",
    "        self.prefix = 0\n",
    "        self.word = 0\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        obj = self\n",
    "        for w in word:\n",
    "            index = ord(w)-ord('a')\n",
    "            if obj.sons[index]==None:\n",
    "                obj.sons[index] = Trie()\n",
    "            obj = obj.sons[index]\n",
    "            obj.prefix+=1\n",
    "        obj.word+=1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        obj = self\n",
    "        for w in word:\n",
    "            index = ord(w)-ord('a')\n",
    "            if obj.sons[index]==None:\n",
    "                return 0\n",
    "            obj = obj.sons[index]\n",
    "        return obj.word\n",
    "\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        obj = self\n",
    "        for w in prefix:\n",
    "            index = ord(w)-ord('a')\n",
    "            if obj.sons[index]==None:\n",
    "                return 0\n",
    "            obj = obj.sons[index]\n",
    "        return obj.prefix\n",
    "\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        obj = self\n",
    "        for w in word:\n",
    "            index = ord(w)-ord('a')\n",
    "            if obj.sons[index]==None:\n",
    "                return\n",
    "            obj = obj.sons[index]\n",
    "            obj.prefix-=1\n",
    "        obj.word-=1\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TrieTree:\n",
    "    def __init__(self):\n",
    "        self.passNum = 0\n",
    "        self.endNum = 0\n",
    "        self.nextList = [None for _ in range(26)]\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = TrieTree()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self.root\n",
    "        node.passNum += 1\n",
    "        for ch in word:\n",
    "            ind = ord(ch) - ord('a')\n",
    "            if node.nextList[ind] == None:\n",
    "                node.nextList[ind] = TrieTree()\n",
    "            node = node.nextList[ind]\n",
    "            node.passNum += 1\n",
    "        node.endNum += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self.root\n",
    "        \n",
    "        for ch in word:\n",
    "            ind = ord(ch) - ord('a')\n",
    "            if node.nextList[ind] == None:\n",
    "                return 0\n",
    "            node = node.nextList[ind]\n",
    "        return node.endNum\n",
    "\n",
    "    def countWordsStartingWith(self, word: str) -> int:\n",
    "        node = self.root\n",
    "        for ch in word:\n",
    "            ind = ord(ch) - ord('a')\n",
    "            if node.nextList[ind] == None:\n",
    "                return 0\n",
    "            node = node.nextList[ind]\n",
    "        return node.passNum\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        if self.countWordsEqualTo(word) > 0:\n",
    "            node = self.root\n",
    "            node.passNum -= 1\n",
    "            for ch in word:\n",
    "                ind = ord(ch) - ord('a')\n",
    "                node.nextList[ind].passNum -= 1\n",
    "                if node.nextList[ind].passNum == 0:\n",
    "                    node.nextList[ind] = None\n",
    "                    return\n",
    "                node = node.nextList[ind]\n",
    "            node.endNum -= 1\n",
    "            \n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 26\n",
    "        self.prefixCount = 0\n",
    "        self.endCount = 0\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self\n",
    "        for ch in word:\n",
    "            n = ord(ch) - ord('a')\n",
    "            if node.children[n] is None:\n",
    "                node.children[n] = Trie()\n",
    "            node = node.children[n]\n",
    "            node.prefixCount += 1\n",
    "        node.endCount += 1\n",
    "\n",
    "    def searchPrefix(self, prefix: str) -> \"Trie\":\n",
    "        node = self\n",
    "        for ch in prefix:\n",
    "            n = ord(ch) - ord('a')\n",
    "            if node.children[n] is None:\n",
    "                return None\n",
    "            node = node.children[n]\n",
    "        return node\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self.searchPrefix(word)\n",
    "        return 0 if node is None else node.endCount\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self.searchPrefix(prefix)\n",
    "        return 0 if node is None else node.prefixCount\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        # if self.countWordsEqualTo(word) == 0:\n",
    "        #    return\n",
    "        node = self\n",
    "        for ch in word:\n",
    "            n = ord(ch) - ord('a')\n",
    "            parent = node\n",
    "            node = node.children[n]\n",
    "            node.prefixCount -= 1\n",
    "            if node.prefixCount == 0:\n",
    "                parent.children[n] = None\n",
    "                return\n",
    "        node.endCount -= 1\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self._childrens = [None] * 26\n",
    "        self._end_cnt = 0\n",
    "        self._pass_cnt = 0\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self\n",
    "\n",
    "        for w in word:\n",
    "            offset = ord(w) - ord('a')\n",
    "            if node._childrens[offset] is None:\n",
    "                node._childrens[offset] = Trie()\n",
    "\n",
    "            node = node._childrens[offset]\n",
    "            node._pass_cnt += 1\n",
    "        \n",
    "        node._end_cnt += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self\n",
    "\n",
    "        for w in word:\n",
    "            offset = ord(w) - ord('a')\n",
    "            if not node._childrens[offset]:\n",
    "                return 0\n",
    "            node = node._childrens[offset]\n",
    "        \n",
    "        return max(node._end_cnt, 0)\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self\n",
    "\n",
    "        for w in prefix:\n",
    "            offset = ord(w) - ord('a')\n",
    "            if not node._childrens[offset]:\n",
    "                return 0\n",
    "            node = node._childrens[offset]\n",
    "        \n",
    "        return max(node._pass_cnt, 0)\n",
    "\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        node = self\n",
    "\n",
    "        if self.countWordsEqualTo(word) == 0:\n",
    "            return\n",
    "\n",
    "        for w in word:\n",
    "            offset = ord(w) - ord('a')\n",
    "            node = node._childrens[offset]\n",
    "            node._pass_cnt -= 1\n",
    "        \n",
    "        node._end_cnt -= 1\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "NUM_CHR = 26\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.prefix = 0\n",
    "        self.end = 0\n",
    "        self.nexts = [None] * NUM_CHR\n",
    "        \n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self\n",
    "        node.prefix += 1\n",
    "        for c in word:\n",
    "            path = ord(c) - ord('a')\n",
    "            if not node.nexts[path]:\n",
    "                node.nexts[path] = Trie()\n",
    "            node = node.nexts[path]\n",
    "            node.prefix += 1\n",
    "        node.end += 1\n",
    "\n",
    "    #查询前缀树里，word单词出现了几次\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        node = self\n",
    "        for c in word:\n",
    "            path = ord(c) - ord('a')\n",
    "            if not node.nexts[path]:\n",
    "                return 0\n",
    "            node = node.nexts[path]\n",
    "        return node.end\n",
    "\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        node = self\n",
    "        for c in prefix:\n",
    "            path = ord(c) - ord('a')\n",
    "            if not node.nexts[path]:\n",
    "                return 0\n",
    "            node = node.nexts[path]\n",
    "        return node.prefix\n",
    "            \n",
    "\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        if self.countWordsEqualTo(word) <= 0:\n",
    "            return\n",
    "        node = self\n",
    "        node.prefix -= 1\n",
    "        for c in word:\n",
    "            path = ord(c) - ord('a')\n",
    "            node.nexts[path].prefix -= 1\n",
    "            if node.nexts[path].prefix == 0:\n",
    "                node.nexts[path] = None\n",
    "                return\n",
    "            node = node.nexts[path]\n",
    "        node.end -= 1\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.countWordsEqualTo(word)\n",
    "# param_3 = obj.countWordsStartingWith(prefix)\n",
    "# obj.erase(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self):\n",
    "        self.children = {}\n",
    "        self.num = 0\n",
    "        self.end = 0  # 以这个为结尾的字符串有多少个\n",
    "\n",
    "\n",
    "# 字典树添加信息\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self.root\n",
    "        for c in word:\n",
    "            if c not in node.children:\n",
    "                node.children[c] = Node()\n",
    "            node = node.children[c]\n",
    "            node.num += 1\n",
    "        node.end += 1\n",
    "\n",
    "    def countWordsEqualTo(self, word: str) -> int:\n",
    "        n = len(word)\n",
    "\n",
    "        def dfs(cur, index):\n",
    "            if index == n:\n",
    "                return cur.end\n",
    "            if word[index] not in cur.children:\n",
    "                return 0\n",
    "            return dfs(cur.children[word[index]], index + 1)\n",
    "\n",
    "        return dfs(self.root, 0)\n",
    "\n",
    "    def countWordsStartingWith(self, prefix: str) -> int:\n",
    "        cur = self.root\n",
    "        for c in prefix:\n",
    "            if c not in cur.children:\n",
    "                return 0\n",
    "            cur = cur.children[c]\n",
    "        return cur.num\n",
    "\n",
    "    def erase(self, word: str) -> None:\n",
    "        node = self.root\n",
    "        for c in word:\n",
    "            cur = node.children[c]\n",
    "            # cur 的一串长度是怎么回事\n",
    "            if cur.num == 1:\n",
    "                del node.children[c]\n",
    "                return\n",
    "            cur.num -= 1\n",
    "            node = cur\n",
    "        node.end -= 1\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TrieNode:\n",
    "    def __init__(self):\n",
    "        self.end = 0\n",
    "        self.children = {}\n",
    "\n",
    "# class Trie:\n",
    "#     def __init__(self):\n",
    "#         self.trie = TrieNode()\n",
    "\n",
    "#     def insert(self, array):\n",
    "#         my_trie = self.trie\n",
    "#         for a in array:\n",
    "#             if a not in my_trie.children:\n",
    "#                 my_trie.children[a] = TrieNode()\n",
    "#             my_trie = my_trie.children[a] \n",
    "#         my_trie.end = True\n",
    "\n",
    "#     def search(self, array):\n",
    "#         my_trie = self.trie\n",
    "#         for a in array:\n",
    "#             if a in my_trie.children:\n",
    "#                 my_trie = my_trie.children[a]\n",
    "#             else:\n",
    "#                 return 0\n",
    "#         return my_trie.count\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.trie = TrieNode()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        my_trie = self.trie\n",
    "        for ch in word:\n",
    "            if ch not in my_trie.children.keys():\n",
    "                my_trie.children[ch] = TrieNode()\n",
    "            my_trie = my_trie.children[ch]\n",
    "        my_trie.end=True\n",
    "        \n",
    "    def search(self, word: str) -> bool:\n",
    "        my_trie = self.trie\n",
    "        for ch in word:\n",
    "            if ch in my_trie.children:\n",
    "                my_trie = my_trie.children[ch]\n",
    "            else:\n",
    "                return False\n",
    "        if my_trie.end:\n",
    "            return True\n",
    "        return False\n",
    "        \n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        my_trie = self.trie\n",
    "        for ch in prefix:\n",
    "            if ch in my_trie.children:\n",
    "                my_trie = my_trie.children[ch]\n",
    "            else:\n",
    "                return False\n",
    "        return True\n",
    "        \n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.dic = defaultdict(list)\n",
    "\n",
    "    def insert(self, word):\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        :type word: str\n",
    "        :rtype: void\n",
    "        \"\"\"\n",
    "        self.dic[word[0]].append(word)\n",
    "\n",
    "    def search(self, word):\n",
    "        \"\"\"\n",
    "        Returns if the word is in the trie.\n",
    "        :type word: str\n",
    "        :rtype: bool\n",
    "        \"\"\"\n",
    "        if word in self.dic[word[0]]:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def startsWith(self, prefix):\n",
    "        \"\"\"\n",
    "        Returns if there is any word in the trie that starts with the given prefix.\n",
    "        :type prefix: str\n",
    "        :rtype: bool\n",
    "        \"\"\"\n",
    "        if len(prefix) == 1:\n",
    "            if self.dic[prefix]:\n",
    "                return True\n",
    "            else:\n",
    "                return False\n",
    "\n",
    "        for w in self.dic[prefix[0]]:\n",
    "            if w.startswith(prefix):\n",
    "                return True\n",
    "        return False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.letter = defaultdict(set)\n",
    "        \n",
    "\n",
    "    def insert(self, word):\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        :type word: str\n",
    "        :rtype: void\n",
    "        \"\"\"\n",
    "        if not word:\n",
    "            return False\n",
    "        \n",
    "        self.letter[word[0]].add(word)\n",
    "        \n",
    "\n",
    "    def search(self, word):\n",
    "        \"\"\"\n",
    "        Returns if the word is in the trie.\n",
    "        :type word: str\n",
    "        :rtype: bool\n",
    "        \"\"\"\n",
    "        if not word:\n",
    "            return False\n",
    "        if self.letter.get(word[0]):\n",
    "            if word in self.letter.get(word[0]):\n",
    "                return True\n",
    "        return False\n",
    "        \n",
    "        \n",
    "\n",
    "    def startsWith(self, prefix):\n",
    "        \"\"\"\n",
    "        Returns if there is any word in the trie that starts with the given prefix.\n",
    "        :type prefix: str\n",
    "        :rtype: bool\n",
    "        \"\"\"\n",
    "        if not prefix:\n",
    "            return False\n",
    "        if self.letter.get(prefix[0]):\n",
    "            for one in self.letter.get(prefix[0]):\n",
    "                if one.startswith(prefix):\n",
    "                    return True\n",
    "        return False\n",
    "        \n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.words=[]\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        \"\"\"\n",
    "        self.words.append(word)\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if the word is in the trie.\n",
    "        \"\"\"\n",
    "        if word in self.words:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if there is any word in the trie that starts with the given prefix.\n",
    "        \"\"\"\n",
    "        for word in self.words:\n",
    "            if word[:len(prefix)]==prefix:\n",
    "                return True\n",
    "        return False\n",
    "        \n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.word_list=[]\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        \"\"\"\n",
    "        self.word_list.append(word)\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if the word is in the trie.\n",
    "        \"\"\"\n",
    "        return word in self.word_list\n",
    "        \n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if there is any word in the trie that starts with the given prefix.\n",
    "        \"\"\"\n",
    "        for one_word in self.word_list:\n",
    "            if prefix == one_word[:len(prefix)]:\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.record = []\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        \"\"\"\n",
    "        self.record.append(word)\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if the word is in the trie.\n",
    "        \"\"\"\n",
    "        if word in self.record:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if there is any word in the trie that starts with the given prefix.\n",
    "        \"\"\"\n",
    "        length = len(prefix)\n",
    "        for key in self.record:\n",
    "            if key[:length] == prefix:\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.dict = []\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        \"\"\"\n",
    "        self.dict.append(word)\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if the word is in the trie.\n",
    "        \"\"\"\n",
    "        for unit in self.dict:\n",
    "            if unit == word:\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if there is any word in the trie that starts with the given prefix.\n",
    "        \"\"\"\n",
    "        n = len(prefix)\n",
    "        for unit in self.dict:\n",
    "            if len(unit) >= n and unit[:n] == prefix:\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.parame = set()\n",
    "\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        \"\"\"\n",
    "        if word not in self.parame:\n",
    "            self.parame.add(word)\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if the word is in the trie.\n",
    "        \"\"\"\n",
    "        if word in self.parame:\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if there is any word in the trie that starts with the given prefix.\n",
    "        \"\"\"\n",
    "        prefix_len = len(prefix)\n",
    "        for word in self.parame:\n",
    "            if len(word) < prefix_len:\n",
    "                continue\n",
    "            if word[0:prefix_len] == prefix:\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)\n",
    "# leetcode submit region end(Prohibit modification and deletion)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.string = ''\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        \"\"\"\n",
    "        self.string += ' ' + word + ' '\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if the word is in the trie.\n",
    "        \"\"\"\n",
    "        return self.string.find(' ' + word + ' ') != -1\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if there is any word in the trie that starts with the given prefix.\n",
    "        \"\"\"\n",
    "        return self.string.find(' ' + prefix) != -1\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.tree = ''\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.tree = self.tree + f'-{word}-'\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        return f'-{word}-' in self.tree\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        return f'-{prefix}' in self.tree\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.string = \"#\"\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.string += word\n",
    "        self.string += \"#\"\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        if \"#\" + word + \"#\" in self.string:\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        if \"#\"+prefix in self.string:\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.words=[]\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.words.append(word)\n",
    "        \n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        if word in self.words:\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        for w in self.words:\n",
    "            if prefix in w:\n",
    "                if prefix == w[0:len(prefix)]:\n",
    "                    return True\n",
    "        return False\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.trie = []\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.trie.append(word)\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        if word in self.trie:\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        for w in self.trie:\n",
    "            if w.startswith(prefix):\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.list = []\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        if word not in self.list:\n",
    "            self.list.append(word)\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        if word in self.list:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        n = len(prefix)\n",
    "        for words in self.list:\n",
    "            if len(words) >= n:\n",
    "                if words[:n] == prefix:\n",
    "                    return True\n",
    "        return False\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.list = []\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        if word not in self.list:\n",
    "            self.list.append(word)\n",
    "            self.list.sort()\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        if word in self.list:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        n = len(prefix)\n",
    "        for words in self.list:\n",
    "            if len(words) >= n:\n",
    "                if words[:n] == prefix:\n",
    "                    return True\n",
    "        return False\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.wordset=set()\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.wordset.add(word)\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        return word in self.wordset\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        flag=False\n",
    "        for w in self.wordset:\n",
    "            if w[:len(prefix)] ==prefix:\n",
    "                flag=True\n",
    "        return flag\n",
    "        #return any([w.startswith(prefix) for w in self.wordset])\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class TreeNode:\n",
    "    def __init__(self, val=''):\n",
    "        self.val = val\n",
    "        self.left = None\n",
    "        self.right = None\n",
    "\n",
    "\n",
    "class Trie:\n",
    "    \"\"\"\n",
    "    利用二叉搜索树实现插入，查找，前缀匹配\n",
    "    \"\"\"\n",
    "    def __init__(self):\n",
    "        self.root = None\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        if not self.root:\n",
    "            self.root = TreeNode(word)\n",
    "            return\n",
    "        ptr = self.root\n",
    "        while ptr:\n",
    "            if word<ptr.val:\n",
    "                if not ptr.left:\n",
    "                    ptr.left = TreeNode(word)\n",
    "                    return\n",
    "                ptr = ptr.left\n",
    "            elif word==ptr.val:\n",
    "                return\n",
    "            else:\n",
    "                if not ptr.right:\n",
    "                    ptr.right = TreeNode(word)\n",
    "                    return\n",
    "                ptr = ptr.right\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        ptr = self.root\n",
    "        while ptr:\n",
    "            if word<ptr.val:\n",
    "                ptr = ptr.left\n",
    "            elif word==ptr.val:\n",
    "                return True\n",
    "            else:\n",
    "                ptr = ptr.right\n",
    "        return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        ptr = self.root\n",
    "        while ptr:\n",
    "            if len(prefix)<=len(ptr.val) and prefix==ptr.val[:len(prefix)]:\n",
    "                return True\n",
    "            elif prefix<ptr.val:\n",
    "                ptr = ptr.left\n",
    "            elif prefix>ptr.val:\n",
    "                ptr = ptr.right\n",
    "        return False\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.roots = []\n",
    "        self.root_words = []\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        for i, root_word in enumerate(self.root_words):\n",
    "            if word.startswith(root_word):\n",
    "                return self.roots[i].insert(word)\n",
    "        self.root_words.append(word)\n",
    "        self.roots.append(Trie())\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        for i, root_word in enumerate(self.root_words):\n",
    "            if root_word == word: return True\n",
    "            elif word.startswith(root_word): return self.roots[i].search(word)\n",
    "        return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        for i, root_word in enumerate(self.root_words):\n",
    "            if root_word.startswith(prefix): return True\n",
    "            elif prefix.startswith(root_word): return self.roots[i].startsWith(prefix)\n",
    "        return False   \n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.roots = []\n",
    "        self.root_words = []\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        for i, root_word in enumerate(self.root_words):\n",
    "            if word.startswith(root_word):\n",
    "                return self.roots[i].insert(word)\n",
    "        self.root_words.append(word)\n",
    "        self.roots.append(Trie())\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        for i, root_word in enumerate(self.root_words):\n",
    "            if root_word == word: return True\n",
    "            elif word.startswith(root_word): return self.roots[i].search(word)\n",
    "        return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        for i, root_word in enumerate(self.root_words):\n",
    "            if root_word.startswith(prefix): return True\n",
    "            elif prefix.startswith(root_word): return self.roots[i].startsWith(prefix)\n",
    "        return False   \n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from typing import Dict, Tuple, TypeVar, Generic, Union\n",
    "\n",
    "KT = TypeVar(\"KT\", str, bytes)\n",
    "VT = TypeVar(\"VT\")\n",
    "\n",
    "\n",
    "class RadixTreeNode(Generic[KT, VT]):\n",
    "    def __init__(self, val: Union[VT, None] = None) -> None:\n",
    "        self.value = val\n",
    "        self.children: Dict[KT, RadixTreeNode[KT, VT]] = {}\n",
    "\n",
    "\n",
    "def _only_kv_pair(dic: Dict) -> Tuple:\n",
    "    for kv_pair in dic.items():\n",
    "        return kv_pair\n",
    "    return None, None\n",
    "\n",
    "\n",
    "def _prefix_match(exist_key: KT, key: KT):\n",
    "    \"\"\"对两个key进行前缀匹配\n",
    "\n",
    "    Args:\n",
    "        exist_key (_type_): 已有key\n",
    "        key (_type_): 新插入key\n",
    "\n",
    "    Returns:\n",
    "        Tuple[]: _description_\n",
    "    \"\"\"\n",
    "    i = 0\n",
    "    for ek, k in zip(exist_key, key):\n",
    "        if ek != k:\n",
    "            break\n",
    "        i += 1\n",
    "    return exist_key[:i], exist_key[i:], key[i:]\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self) -> None:\n",
    "        self.root = RadixTreeNode[KT, VT]()\n",
    "\n",
    "    def _set(self, node: RadixTreeNode[KT, VT], key: KT, val: VT) -> Union[VT, None]:\n",
    "        for exist_key, child in node.children.items():\n",
    "            prefix, unmatch_ek, unmatch_k = _prefix_match(exist_key, key)\n",
    "            if not unmatch_ek:\n",
    "                if not unmatch_k:\n",
    "                    # 如果两key相等，则替换值\n",
    "                    old_val = child.value\n",
    "                    child.value = val\n",
    "                    return old_val\n",
    "                else:\n",
    "                    # 如果旧key匹完，新key未完，则递归插入\n",
    "                    return self._set(child, unmatch_k, val)\n",
    "            # 如果旧key未完，且两者有公共前缀，则节点分裂\n",
    "            if prefix:\n",
    "                prefix_node = RadixTreeNode[KT, VT]()\n",
    "                prefix_node.children[unmatch_ek] = child\n",
    "                del node.children[exist_key]\n",
    "                node.children[prefix] = prefix_node\n",
    "                if not unmatch_k:\n",
    "                    prefix_node.value = val\n",
    "                    return None\n",
    "                else:\n",
    "                    return self._set(prefix_node, unmatch_k, val)\n",
    "        node.children[key] = RadixTreeNode[KT, VT](val)\n",
    "        return None\n",
    "\n",
    "    def _get(self, node: RadixTreeNode[KT, VT], key: KT) -> VT:\n",
    "        for exist_key, child in node.children.items():\n",
    "            prefix, unmatch_ek, unmatch_k = _prefix_match(exist_key, key)\n",
    "            # 旧key未完说明元素不存在，旧key已完则根据新key情况直接返回值/递归查询\n",
    "            if not unmatch_ek:\n",
    "                if not unmatch_k:\n",
    "                    return child.value\n",
    "                else:\n",
    "                    return self._get(child, unmatch_k)\n",
    "\n",
    "    def _del(self, node: RadixTreeNode[KT, VT], key: KT) -> VT:\n",
    "        for exist_key, child in node.children.items():\n",
    "            prefix, unmatch_ek, unmatch_k = _prefix_match(exist_key, key)\n",
    "            if not unmatch_ek:\n",
    "                if not unmatch_k:\n",
    "                    old_val = child.value\n",
    "                    child.value = None\n",
    "                    if len(child.children) <= 1:\n",
    "                        k, v = _only_kv_pair(child.children)\n",
    "                        del node.children[exist_key]\n",
    "                        if k:\n",
    "                            node.children[exist_key + k] = v\n",
    "                    return old_val\n",
    "                else:\n",
    "                    return self._del(child, unmatch_k)\n",
    "\n",
    "    def _iter(self, node: RadixTreeNode[KT, VT], prefix: KT):\n",
    "        for exist_key, child in node.children.items():\n",
    "            now_key = prefix + exist_key\n",
    "            if child.value:\n",
    "                yield now_key, child.value\n",
    "            yield from self._iter(child, now_key)\n",
    "\n",
    "    def __getitem__(self, key: KT) -> VT:\n",
    "        return self._get(self.root, key)\n",
    "\n",
    "    def __setitem__(self, key: KT, val: VT) -> None:\n",
    "        self._set(self.root, key, val)\n",
    "\n",
    "    def __delitem__(self, key: KT) -> None:\n",
    "        self._del(self.root, key)\n",
    "\n",
    "    def __contains__(self, key: KT) -> bool:\n",
    "        return self._get(self.root, key) is not None\n",
    "\n",
    "    def __iter__(self):\n",
    "        yield from self._iter(self.root, \"\")\n",
    "\n",
    "    def _starts_with(self, node: RadixTreeNode[KT, VT], key: KT):\n",
    "        for exist_key, child in node.children.items():\n",
    "            prefix, unmatch_ek, unmatch_k = _prefix_match(exist_key, key)\n",
    "            if not unmatch_k: return True\n",
    "            if unmatch_ek: continue\n",
    "            return self._starts_with(child, unmatch_k)\n",
    "        return False\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self._set(self.root, word, True)\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        return self._get(self.root, word) is True\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        return self._starts_with(self.root, prefix)\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.dict_word=[]\n",
    "        self.dict_pre=[]\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        if word not in self.dict_word:\n",
    "            self.dict_word.append(word)\n",
    "        for i in range(1,len(word)+1):\n",
    "            if word[:i] not in self.dict_pre:\n",
    "                self.dict_pre.append(word[:i])\n",
    "    def search(self, word: str) -> bool:\n",
    "        if word in self.dict_word:\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        if prefix in self.dict_pre:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.trie_dict=set()\n",
    "        self.start_dict=set()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        if word not in self.trie_dict:\n",
    "            self.trie_dict.add(word)\n",
    "            for i in range(len(word)):\n",
    "                if word[0:i+1] not in self.start_dict:\n",
    "                    self.start_dict.add(word[0:i+1])\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        if word in self.trie_dict:\n",
    "            return True\n",
    "        else: return  False\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        if prefix in self.start_dict:\n",
    "            return True \n",
    "        else: return False\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.data_search = defaultdict(int)\n",
    "        self.data_prefix = defaultdict(int)\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.data_search[word] += 1\n",
    "        length = len(word)\n",
    "        for i in range(1, length+1):\n",
    "            self.data_prefix[word[:i]] += 1\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        if self.data_search[word] > 0:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        if self.data_prefix[prefix] > 0:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.stack=[]\n",
    "        self.trie={}\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        for i in range(len(word)):\n",
    "            end=len(word)-i\n",
    "            if word[:end] not in self.trie:\n",
    "                self.trie[word[:end]]=0\n",
    "        self.stack.append(word)\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        if word in self.stack:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        \n",
    "        if prefix in self.trie:\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.word = set()\n",
    "        self.prefix = set()\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.word.add(word)\n",
    "        length = len(word)\n",
    "        for i in range(length):\n",
    "            self.prefix.add(word[:i])\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        return word in self.word\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        return prefix in self.prefix or prefix in self.word\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.words = set()\n",
    "        self.prefixs = set()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        self.words.add(word)\n",
    "        for i in range(len(word),0,-1):\n",
    "            temp_prefix = word[:i]\n",
    "            if temp_prefix in self.prefixs:\n",
    "                continue\n",
    "            self.prefixs.add(temp_prefix)\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        return word in self.words\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        return prefix in self.prefixs\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.trie_ = collections.defaultdict(dict)\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        tmp = self.trie_\n",
    "        for w in word:\n",
    "            if w not in tmp:\n",
    "                tmp[w] = {}\n",
    "            tmp = tmp[w]\n",
    "        tmp['#'] = {}\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        tmp = self.trie_\n",
    "        for w in word:\n",
    "            if w not in tmp: return False\n",
    "            tmp = tmp[w]\n",
    "        return '#' in tmp\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        tmp = self.trie_\n",
    "        for w in prefix:\n",
    "            if w not in tmp: return False\n",
    "            tmp = tmp[w]\n",
    "        return True\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.lookup = {}\n",
    "        \n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        \"\"\"\n",
    "        Inserts a word into the trie.\n",
    "        \"\"\"\n",
    "        tree = self.lookup\n",
    "        for a in word:\n",
    "            if a not in tree:\n",
    "                tree[a] = {}\n",
    "            tree = tree[a]\n",
    "        # 单词结束标志\n",
    "        tree[\"#\"] = \"#\"\n",
    "        \n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if the word is in the trie.\n",
    "        \"\"\"\n",
    "        tree = self.lookup\n",
    "        for a in word:\n",
    "            if a not in tree:\n",
    "                return False\n",
    "            tree = tree[a]\n",
    "        if \"#\" in tree:\n",
    "            return True\n",
    "        return False\n",
    "        \n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        \"\"\"\n",
    "        Returns if there is any word in the trie that starts with the given prefix.\n",
    "        \"\"\"\n",
    "        tree = self.lookup\n",
    "        for a in prefix:\n",
    "            if a not in tree:\n",
    "                return False\n",
    "            tree = tree[a]\n",
    "        return True\n",
    "        \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = {}\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        p = self.root\n",
    "        for c in word:\n",
    "            if c not in p:\n",
    "                p[c] = {}\n",
    "            p = p[c]\n",
    "        p[\"#\"] = True\n",
    "\n",
    "    def find(self, prefix):\n",
    "        p = self.root\n",
    "        for c in prefix:\n",
    "            if c not in p:\n",
    "                return None\n",
    "            p = p[c]\n",
    "        return p\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        return self.find(prefix) is not None\n",
    "        \n",
    "    def search(self, word: str) -> bool:\n",
    "        node = self.find(word)\n",
    "        return node is not None and '#' in node\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.node = dict()\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        now = self.node\n",
    "        for i in word:\n",
    "            if i not in now:\n",
    "                now[i] = dict()\n",
    "            now = now[i]\n",
    "        now['end'] = 1\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        now = self.node\n",
    "        for i in word:\n",
    "            if i not in now:\n",
    "                return False\n",
    "            now = now[i]\n",
    "\n",
    "        return True if 'end' in now else False       \n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        now = self.node\n",
    "        for i in prefix:\n",
    "            if i not in now:\n",
    "                return False\n",
    "            now = now[i]\n",
    "\n",
    "        return True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.child = collections.defaultdict(dict)\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        nownode = self.child\n",
    "        for s in word:\n",
    "            if s not in nownode.keys():\n",
    "                nownode[s] = collections.defaultdict(dict)\n",
    "            nownode = nownode[s]\n",
    "        \n",
    "        nownode['#'] = '#'\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        nownode = self.child\n",
    "        for s in word:\n",
    "            if s in nownode.keys():\n",
    "                nownode = nownode[s]\n",
    "            else:\n",
    "                return False\n",
    "        \n",
    "        return '#' in nownode.keys()\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        nownode = self.child\n",
    "        for s in prefix:\n",
    "            if s in nownode.keys():\n",
    "                nownode = nownode[s]\n",
    "            else:\n",
    "                return False\n",
    "        return True\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.char_dict = {}\n",
    "        self._keyword = \"__keyword__\"\n",
    "\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        current_dict = self.char_dict\n",
    "        for char in word:\n",
    "            current_dict = current_dict.setdefault(char, {})\n",
    "        if self._keyword not in current_dict:\n",
    "            current_dict[self._keyword] = word \n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        curent_dict = self.char_dict\n",
    "        for char in word:\n",
    "            if char in curent_dict:\n",
    "                curent_dict = curent_dict[char]\n",
    "            else:\n",
    "                return False\n",
    "        if curent_dict.get(self._keyword):\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        curent_dict = self.char_dict\n",
    "        for char in prefix:\n",
    "            if char in curent_dict:\n",
    "                curent_dict = curent_dict[char]\n",
    "            else:\n",
    "                return False\n",
    "        return True\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, word):\n",
    "        self.word = word\n",
    "        self.children = []\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = Node('')\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        n = self.root\n",
    "        \n",
    "        for w in word:\n",
    "            n_move_flag = False\n",
    "            for c in n.children:\n",
    "                if w == c.word:\n",
    "                    n = c\n",
    "                    n_move_flag = True\n",
    "                    break\n",
    "            if not n_move_flag:\n",
    "                n.children.append(Node(w))\n",
    "                n = n.children[-1]\n",
    "        n.children.append(Node('#'))\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        n = self.root\n",
    "        for w in word:\n",
    "            n_move_flag = False\n",
    "            for c in n.children:\n",
    "                if w == c.word:\n",
    "                    n = c\n",
    "                    n_move_flag = True\n",
    "                    break\n",
    "            if not n_move_flag:\n",
    "                return False\n",
    "        for c in n.children:\n",
    "            if c.word == '#':\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        n = self.root\n",
    "        \n",
    "        for w in prefix:\n",
    "            n_move_flag = False\n",
    "            for c in n.children:\n",
    "                if w == c.word:\n",
    "                    n = c\n",
    "                    n_move_flag = True\n",
    "                    break\n",
    "            if not n_move_flag:\n",
    "                return False\n",
    "        return True\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class NODE:\n",
    "    def __init__(self):\n",
    "        self.end = False\n",
    "        self.np = []\n",
    "        self.nv = []\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.head = NODE()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        p = self.head\n",
    "        for i in range(len(word)):\n",
    "            s = False\n",
    "            for j in range(len(p.nv)):\n",
    "                if word[i] == p.nv[j]:\n",
    "                    p = p.np[j]\n",
    "                    s = True\n",
    "                    break\n",
    "            if s is False:\n",
    "                p.nv += [word[i]]\n",
    "                new = NODE()\n",
    "                p.np += [new]\n",
    "                p = new\n",
    "        p.end = True\n",
    "    def search(self, word: str) -> bool:\n",
    "        p = self.head\n",
    "        for i in range(len(word)):\n",
    "            s = False\n",
    "            for j in range(len(p.nv)):\n",
    "                if word[i] == p.nv[j]:\n",
    "                    p = p.np[j]\n",
    "                    s = True\n",
    "                    break\n",
    "            if s is False:\n",
    "                return False\n",
    "        if p.end is False:\n",
    "            return False\n",
    "        else:\n",
    "            return True\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        p = self.head\n",
    "        for i in range(len(prefix)):\n",
    "            s = False\n",
    "            for j in range(len(p.nv)):\n",
    "                if prefix[i] == p.nv[j]:\n",
    "                    p = p.np[j]\n",
    "                    s = True\n",
    "                    break\n",
    "            if s is False:\n",
    "                return False\n",
    "        return True\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.array = [[-1]*26]\n",
    "        self.base = ord('a')\n",
    "        self.isend = [False]\n",
    "        \n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = 0\n",
    "        for c in word:\n",
    "            if self.array[node][ord(c)-self.base] == -1:\n",
    "                self.array[node][ord(c)-self.base] = len(self.array)\n",
    "                self.array.append([-1]*26)\n",
    "                self.isend.append(False)\n",
    "            node = self.array[node][ord(c)-self.base]\n",
    "        self.isend[node] = True\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        node = 0\n",
    "        for c in word:\n",
    "            if self.array[node][ord(c)-self.base] == -1:\n",
    "                return False\n",
    "            node = self.array[node][ord(c)-self.base]\n",
    "        return self.isend[node]\n",
    "        \n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        node = 0\n",
    "        for c in prefix:\n",
    "            if self.array[node][ord(c)-self.base] == -1:\n",
    "                return False\n",
    "            node = self.array[node][ord(c)-self.base]\n",
    "        return True\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Tree:\n",
    "    def __init__(self, val):\n",
    "        self.val = val\n",
    "        self.childs = []\n",
    "        self.child_vals = []\n",
    "        self.isend = False\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = Tree('root')\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        if self.search(word):\n",
    "            return\n",
    "        node = self.root\n",
    "        for char in word:\n",
    "            # print(word, char, node.val, node.child_vals)\n",
    "            if char not in node.child_vals:\n",
    "                node.child_vals.append(char)\n",
    "                node.childs.append(Tree(char))\n",
    "                node = node.childs[-1]\n",
    "            else:\n",
    "                i = node.child_vals.index(char)\n",
    "                # print(word, i, char)\n",
    "                node = node.childs[i]\n",
    "        node.isend = True\n",
    "            # print(char, node.val, node.child_vals)\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        node = self.root\n",
    "        for char in word:\n",
    "            # print(char, node.val, node.child_vals)\n",
    "            if char not in node.child_vals:\n",
    "                return False\n",
    "            else:\n",
    "                for child in node.childs:\n",
    "                    if child.val == char:\n",
    "                        break\n",
    "                node = child\n",
    "        if node.isend:\n",
    "            return True               \n",
    "        else:\n",
    "            # print(node.val, node.child_vals)\n",
    "            return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        node = self.root\n",
    "        for char in prefix:\n",
    "            # print(prefix, char, node.val, node.child_vals)\n",
    "            if char not in node.child_vals:\n",
    "                return False\n",
    "            else:\n",
    "                for child in node.childs:\n",
    "                    if child.val == char:\n",
    "                        break\n",
    "                node = child\n",
    "        return True  \n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.children = {}\n",
    "        self.val = \"\"\n",
    "        self.w_tag = False\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        cur = self\n",
    "        for s_i in range(len(word)):\n",
    "            s = word[s_i]\n",
    "            \n",
    "            if s not in cur.children:\n",
    "                newNode = Trie() \n",
    "                cur.children[s] = newNode    \n",
    "            # if s_i == len(word)-1:\n",
    "            #     cur.children[s].w_tag = True    \n",
    "            cur = cur.children[s]\n",
    "        cur.w_tag = True\n",
    "    def search(self, word: str) -> bool:\n",
    "        cur = self\n",
    "        for s_i in range(len(word)):\n",
    "            s = word[s_i]\n",
    "            \n",
    "            if s not in cur.children:\n",
    "                return False\n",
    "            else:\n",
    "                # if s_i == len(word)-1 :\n",
    "                #     return cur.children[s].w_tag == True  \n",
    "                cur = cur.children[s]\n",
    "        return cur.w_tag == True\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        cur = self\n",
    "        for s_i in range(len(prefix)):\n",
    "            s = prefix[s_i]\n",
    "            if s not in cur.children:\n",
    "                return False\n",
    "            else:\n",
    "                cur = cur.children[s]\n",
    "        return True\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, val=\"\"):\n",
    "        self.val = val\n",
    "        self.is_end = False\n",
    "        self.next = dict()\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.head = Node()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self.head\n",
    "        n = len(word)\n",
    "        for i, c in enumerate(word):\n",
    "            d = node.next\n",
    "            if c not in d:\n",
    "                d[c] = Node(c)\n",
    "            if i == n-1:\n",
    "                d[c].is_end = True\n",
    "            node = d[c]\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        node = self.head\n",
    "        for c in word:\n",
    "            d = node.next\n",
    "            if c not in d:\n",
    "                return False\n",
    "            node = d[c]\n",
    "        return d[c].is_end\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        node = self.head\n",
    "        for c in prefix:\n",
    "            d = node.next\n",
    "            if c not in d:\n",
    "                return False\n",
    "            node = d[c]\n",
    "        return True\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Node:\n",
    "    def __init__(self):\n",
    "        self.children = collections.defaultdict(Node)\n",
    "        self.isword = False\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.root = Node()\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        current = self.root\n",
    "        for w in word:\n",
    "            current = current.children[w]\n",
    "        current.isword = True\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        current = self.root\n",
    "        for w in word:\n",
    "            current = current.children.get(w)\n",
    "            if current == None:\n",
    "                return False\n",
    "        return current.isword\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        current = self.root\n",
    "        for w in prefix:\n",
    "            current = current.children.get(w)\n",
    "            if current == None:\n",
    "                return False\n",
    "        return True\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self, char=None):\n",
    "        self.char: str = char\n",
    "        self.children: Dict[str, 'no_208_Trie'] = {}   # {char: Trie}\n",
    "        self.is_end: bool = False\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        char_list = list(word)\n",
    "        node = self\n",
    "        for c in char_list:\n",
    "            if node.children.get(c) == None:\n",
    "                node.children[c] = Trie(c)\n",
    "            node = node.children[c]\n",
    "        node.is_end = True\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        c = word[0]\n",
    "        if self.children.get(c) == None:\n",
    "            return False\n",
    "        if len(word) == 1 and self.children[c].is_end:\n",
    "            return True\n",
    "        elif len(word) == 1 and not self.children[c].is_end:\n",
    "            return False\n",
    "        return self.children[c].search(word[1:])\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        c = prefix[0]\n",
    "        if self.children.get(c) == None:\n",
    "            return False\n",
    "        if len(prefix) == 1:\n",
    "            return True\n",
    "        return self.children[c].startsWith(prefix[1:])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.children = [None] * 26\n",
    "        self.isEnd = False\n",
    "\n",
    "    def searchPrefix(self, prefix:str) -> \"Trie\":\n",
    "        node = self\n",
    "        for ch in prefix:\n",
    "            ch = ord(ch) - ord(\"a\")\n",
    "            if not node.children[ch]:\n",
    "                return None\n",
    "            node = node.children[ch]\n",
    "        return node\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node = self\n",
    "        for ch in word:\n",
    "            ch = ord(ch) - ord(\"a\")\n",
    "            if not node.children[ch]:\n",
    "                node.children[ch] = Trie()\n",
    "            node = node.children[ch]\n",
    "        node.isEnd = True\n",
    "\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        node = self.searchPrefix(word)\n",
    "        return node is not None and node.isEnd\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        return self.searchPrefix(prefix) is not None\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "    def __init__(self):\n",
    "        self.children=[None]*26 # 26叉树？\n",
    "        self.isEnd=False\n",
    "\n",
    "    def searchPrefix(self,prefix:str)->\"Trie\":\n",
    "        node=self\n",
    "        for ch in prefix: # 对于这个字符串中的每一个字符\n",
    "            ch=ord(ch)-ord('a') # 变成ascii码，相减得到0，1，2，3...\n",
    "            if not node.children[ch]: # 如果这个码没出现过\n",
    "                return None\n",
    "            node=node.children[ch] # 对应字母\n",
    "        return node\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        node=self\n",
    "        for ch in word:\n",
    "            ch=ord(ch)-ord('a') # 找到索引\n",
    "            if not node.children[ch]:\n",
    "                node.children[ch]=Trie() # 创建一个26叉树跟着这个节点\n",
    "            node=node.children[ch]\n",
    "        node.isEnd=True # 插入完成，标志尾节点\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        node=self.searchPrefix(word) # 对于每一个单词，查询\n",
    "        return node is not None and node.isEnd\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        return self.searchPrefix(prefix) is not None\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.trie = {}\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        cur_trie = self.trie\n",
    "        for index in range(len(word)):\n",
    "            char = word[index]\n",
    "            if char in cur_trie:\n",
    "                if index == len(word) - 1:\n",
    "                    cur_trie[char][\"is_end\"] = True\n",
    "                    return\n",
    "                cur_trie = cur_trie[char][\"trie\"]\n",
    "            else:\n",
    "                if index == len(word) - 1:\n",
    "                    cur_trie[char] = {\"trie\":{},\"is_end\":True}\n",
    "                else:\n",
    "                    cur_trie[char] = {\"trie\":{},\"is_end\":False}\n",
    "                    cur_trie = cur_trie[char][\"trie\"]\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        cur_trie = self.trie\n",
    "        for index in range(len(word)):\n",
    "            char = word[index]\n",
    "            if char in cur_trie:\n",
    "                if index == len(word) - 1:\n",
    "                    return cur_trie[char][\"is_end\"]\n",
    "                cur_trie = cur_trie[char][\"trie\"]\n",
    "            else:\n",
    "                return False\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "\n",
    "        cur_trie = self.trie\n",
    "        for index in range(len(prefix)):\n",
    "            char = prefix[index]\n",
    "            if char in cur_trie:\n",
    "                cur_trie = cur_trie[char][\"trie\"]\n",
    "            else:\n",
    "                return False\n",
    "        \n",
    "        return True\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.tree = [None] * 26\n",
    "        self.isend = False\n",
    "\n",
    "    def insert(self, word: str) -> None:\n",
    "        if len(word) > 0:\n",
    "            idx = ord(word[0]) - ord('a')\n",
    "            if not self.tree[idx]:\n",
    "                self.tree[idx] = Trie()\n",
    "            self.tree[idx].insert(word[1:])\n",
    "        elif len(word) == 0:\n",
    "            self.isend = True\n",
    "\n",
    "    def search(self, word: str) -> bool:\n",
    "        # print(word)\n",
    "        if len(word) == 0:\n",
    "            if self.isend:\n",
    "                return True\n",
    "            return False\n",
    "        idx = ord(word[0]) - ord('a')\n",
    "        if not self.tree[idx]:\n",
    "            return False\n",
    "        else:\n",
    "            return self.tree[idx].search(word[1:])\n",
    "\n",
    "\n",
    "    def startsWith(self, prefix: str) -> bool:\n",
    "        #print(prefix)\n",
    "        if len(prefix) == 0:\n",
    "            return True\n",
    "        idx = ord(prefix[0]) - ord('a')\n",
    "        #print(idx, self.tree)\n",
    "        if not self.tree[idx]:\n",
    "            return False\n",
    "        else:\n",
    "            return self.tree[idx].startsWith(prefix[1:])\n",
    "\n",
    "\n",
    "\n",
    "# Your Trie object will be instantiated and called as such:\n",
    "# obj = Trie()\n",
    "# obj.insert(word)\n",
    "# param_2 = obj.search(word)\n",
    "# param_3 = obj.startsWith(prefix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def rangeAddQueries(self, n: int, queries: List[List[int]]) -> List[List[int]]:\n",
    "        N = n+10\n",
    "        b = [[0] * N for _ in range(N)]\n",
    "        c = [[0] * n for _ in range(n)]\n",
    "\n",
    "        def insert(x1, y1, x2, y2, c):\n",
    "            b[x1][y1] += c\n",
    "            b[x2 + 1][y1] -= c\n",
    "            b[x1][y2 + 1] -= c\n",
    "            b[x2 + 1][y2 + 1] += c\n",
    "\n",
    "        for x1, y1, x2, y2 in queries:\n",
    "            insert(x1, y1, x2, y2, 1)\n",
    "\n",
    "        # 通过对差分矩阵求前缀和\n",
    "        for i in range(0, n):\n",
    "            for j in range(0, n):\n",
    "                b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]\n",
    "                c[i][j] = b[i][j]\n",
    "        return c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Trie:\r\n",
    "    def __init__(self):\r\n",
    "        self.child = dict()\r\n",
    "        self.isWord = False\r\n",
    "    \r\n",
    "    def insert(self, word: str):\r\n",
    "        root = self\r\n",
    "        for c in word:\r\n",
    "            if c not in root.child:\r\n",
    "                root.child[c] = Trie()\r\n",
    "            root = root.child[c]\r\n",
    "        root.isWord = True\r\n",
    "\r\n",
    "\r\n",
    "class Solution:\r\n",
    "    def indexPairs(self, text: str, words: List[str]) -> List[List[int]]:\r\n",
    "        n = len(text)\r\n",
    "\r\n",
    "        T = Trie()\r\n",
    "        for word in words:\r\n",
    "            T.insert(word)\r\n",
    "        \r\n",
    "        res = []\r\n",
    "        for i, c in enumerate(text):\r\n",
    "            root = T\r\n",
    "            if c not in root.child:\r\n",
    "                continue\r\n",
    "            j = i\r\n",
    "            while j < n and text[j] in root.child:\r\n",
    "                root = root.child[text[j]]\r\n",
    "                if root.isWord == True:\r\n",
    "                    res.append([i, j])\r\n",
    "                j += 1\r\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = []\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.nums.append(val)\n",
    "        return val not in self.nums[:-1]\n",
    "\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.nums:\n",
    "            return False\n",
    "        self.nums.remove(val)\n",
    "        return True\n",
    "        \n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.l = []\n",
    "        self.dict = {}\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.dict:\n",
    "            if len(self.dict[val])!=0:\n",
    "                self.dict[val].append(len(self.l))\n",
    "                self.l.append(val)\n",
    "                return False\n",
    "        self.dict[val]=[len(self.l)]\n",
    "        self.l.append(val)\n",
    "        return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.dict:\n",
    "            return False\n",
    "        if len(self.dict[val])==0:\n",
    "            return False\n",
    "        if self.l[-1]==val:\n",
    "            self.dict[val].pop()\n",
    "            self.l.pop()\n",
    "            return True\n",
    "        self.l[self.dict[val][-1]] = self.l[-1]\n",
    "        \n",
    "        for i in range(len(self.dict[self.l[-1]])):  \n",
    "            if self.dict[val][-1]<=self.dict[self.l[-1]][i]:\n",
    "                self.dict[self.l[-1]].insert(i,self.dict[val][-1])\n",
    "                break\n",
    "\n",
    "        self.dict[self.l[-1]].pop()\n",
    "        self.l.pop()\n",
    "        self.dict[val].pop()\n",
    "       \n",
    "        return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.l)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.cache = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.cache:\n",
    "            self.cache.append(val)\n",
    "            return False\n",
    "        else:\n",
    "            self.cache.append(val)\n",
    "            return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.cache:\n",
    "            return False\n",
    "        \n",
    "        inx = self.cache.index(val)\n",
    "        self.cache[inx] = self.cache[len(self.cache)-1]\n",
    "        del self.cache[len(self.cache)-1]\n",
    "        return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.cache)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.l = []\n",
    "        self.dict = {}\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.dict:\n",
    "            if len(self.dict[val])!=0:\n",
    "                self.dict[val].append(len(self.l))\n",
    "                self.l.append(val)\n",
    "                return False\n",
    "        self.dict[val]=[len(self.l)]\n",
    "        self.l.append(val)\n",
    "        return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.dict:\n",
    "            return False\n",
    "        if len(self.dict[val])==0:\n",
    "            return False\n",
    "        if self.l[-1]==val:\n",
    "            self.dict[val].pop()\n",
    "            self.l.pop()\n",
    "            return True\n",
    "        self.l[self.dict[val][-1]] = self.l[-1]\n",
    "        \n",
    "        for i in range(len(self.dict[self.l[-1]])):  \n",
    "            if self.dict[val][-1]<=self.dict[self.l[-1]][i]:\n",
    "                self.dict[self.l[-1]].insert(i,self.dict[val][-1])\n",
    "                break\n",
    "\n",
    "        self.dict[self.l[-1]].pop()\n",
    "        self.l.pop()\n",
    "        self.dict[val].pop()\n",
    "       \n",
    "        return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.l)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.tables = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if not val in self.tables:\n",
    "            self.tables.append(val)\n",
    "            return True\n",
    "        else:\n",
    "            self.tables.append(val)\n",
    "            return False\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.tables:\n",
    "            self.tables.remove(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False        \n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        index = random.randint(0,len(self.tables)-1)\n",
    "        return self.tables[index]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.lst = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.lst:\n",
    "            self.lst.append(val)\n",
    "            return False\n",
    "        self.lst.append(val)\n",
    "        return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.lst:\n",
    "            self.lst.remove(val)\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.lst)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.obj = []\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.obj:\n",
    "            self.obj.append(val)\n",
    "            return False\n",
    "        else:\n",
    "            self.obj.append(val)\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.obj:\n",
    "            self.obj.remove(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.obj)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict\n",
    "import random\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.l = []\n",
    "        \n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the collection. Returns true if the collection did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        x = True\n",
    "        if val in self.l:\n",
    "            x = False\n",
    "        self.l.append(val)\n",
    "        return x\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the collection. Returns true if the collection contained the specified element.\n",
    "        \"\"\"\n",
    "        if val not in self.l:\n",
    "            return False\n",
    "        else:\n",
    "            self.l.remove(val)\n",
    "            return True\n",
    "\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the collection.\n",
    "        \"\"\"\n",
    "        x = random.randint(0, len(self.l) - 1)\n",
    "        return self.l[x]\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        import random\n",
    "        self.list = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.list:\n",
    "            self.list.append(val)\n",
    "            return False\n",
    "        else:\n",
    "            self.list.append(val)\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.list:\n",
    "            self.list.remove(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.list)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.lis = []\n",
    "        self.dict_ = dict()\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.lis:\n",
    "            self.lis.append(val)\n",
    "            return False\n",
    "        else:\n",
    "            self.lis.append(val)\n",
    "            return True\n",
    "        \n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        lenget = len(self.lis)\n",
    "        if val in self.lis:\n",
    "            if self.lis[lenget-1]==val:\n",
    "                self.lis.pop()\n",
    "                return True\n",
    "            else:\n",
    "                index = self.lis.index(val)\n",
    "                self.lis[index],  self.lis[lenget-1] = self.lis[lenget-1],  self.lis[index]\n",
    "                self.lis.pop()\n",
    "                return True\n",
    "        return False\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.lis)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.obj = list()\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.obj:\n",
    "            self.obj.append(val)\n",
    "            return False\n",
    "        else:\n",
    "            self.obj.append(val)\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.obj:\n",
    "            self.obj.remove(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.obj)\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.collect = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        n = len(self.collect)\n",
    "        result = True\n",
    "        for i in range(n):\n",
    "            if self.collect[i] == val:\n",
    "                result = False\n",
    "                break\n",
    "        self.collect.append(val)\n",
    "        return result\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        n = len(self.collect)\n",
    "        result = False\n",
    "        for i in range(n):\n",
    "            if self.collect[i] == val:\n",
    "                result = True\n",
    "                break\n",
    "        if result:\n",
    "            self.collect.remove(val)\n",
    "        return result\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        out = random.choice(self.collect)\n",
    "        return out\n",
    "        \n",
    "\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# class RandomizedCollection:\n",
    "\n",
    "#     def __init__(self):\n",
    "#         self.array = []\n",
    "#         self.map = dict()\n",
    "#         self.size = 0\n",
    "\n",
    "\n",
    "#     def insert(self, val: int) -> bool:\n",
    "#         if val in self.map.keys():\n",
    "#             self.map[val].append(self.size)\n",
    "#             self.size += 1\n",
    "#             self.array.append(val)\n",
    "#             return False\n",
    "#         else:\n",
    "#             self.map[val]=[self.size]\n",
    "#             self.size += 1\n",
    "#             self.array.append(val)\n",
    "#             return True\n",
    "\n",
    "\n",
    "#     def remove(self, val: int) -> bool:\n",
    "#         if val in self.map.keys():\n",
    "#             temp = self.map[val].pop(0)\n",
    "#             temp_num = self.array[self.size-1]\n",
    "#             self.array[temp] = temp_num\n",
    "#             if self.map[temp_num]:\n",
    "#                 self.map[temp_num].pop(0)\n",
    "#             self.map[temp_num].append(temp)\n",
    "#             self.size -= 1\n",
    "#             return True\n",
    "#         else:\n",
    "#             return False\n",
    "\n",
    "\n",
    "\n",
    "#     def getRandom(self) -> int:\n",
    "#         return choice(self.array)\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.l = []\n",
    "        \n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the collection. Returns true if the collection did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        x = True\n",
    "        if val in self.l:\n",
    "            x = False\n",
    "        self.l.append(val)\n",
    "        return x\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the collection. Returns true if the collection contained the specified element.\n",
    "        \"\"\"\n",
    "        if val not in self.l:\n",
    "            return False\n",
    "        else:\n",
    "            self.l.remove(val)\n",
    "            return True\n",
    "\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the collection.\n",
    "        \"\"\"\n",
    "        x = random.randint(0, len(self.l) - 1)\n",
    "        return self.l[x]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.cache = []\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.cache:\n",
    "            self.cache.append(val)\n",
    "            return False\n",
    "        else:\n",
    "            self.cache.append(val)\n",
    "            return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.cache:\n",
    "            self.cache.remove(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.cache)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.collection = dict()\n",
    "        self.arr = list()\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.arr.append(val)\n",
    "        if val in self.collection:\n",
    "            self.collection[val] += 1\n",
    "            return False\n",
    "        else:\n",
    "            self.collection.update({val: 1})\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.collection:\n",
    "            index = self.arr.index(val)\n",
    "            self.arr.pop(index)\n",
    "            self.collection[val] -= 1\n",
    "            if self.collection[val] == 0:\n",
    "                self.collection.pop(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        r = random.choice(self.arr)\n",
    "        return r\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.dict = {}\n",
    "        self.list = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.dict:\n",
    "            self.dict[val] += 1\n",
    "            self.list.append(val)\n",
    "            return(False)\n",
    "        else:\n",
    "            self.dict[val] = 1\n",
    "            self.list.append(val)\n",
    "            return(True)\n",
    "        \n",
    "        \n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.dict:\n",
    "            if self.dict[val] > 1:\n",
    "                self.dict[val] -= 1\n",
    "            else:\n",
    "                del self.dict[val]\n",
    "            self.list.remove(val)\n",
    "            return(True)\n",
    "        else:\n",
    "            return(False)\n",
    "        \n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return(random.sample(self.list ,1)[0])\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.vals1 = collections.defaultdict(int)\n",
    "        self.vals2 = []\n",
    "        self.all = collections.defaultdict(int)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        ret = True\n",
    "        if self.vals1[val] > 0: ret = False\n",
    "        self.vals1[val] += 1\n",
    "        if self.vals1[val] > self.all[val]:\n",
    "            self.all[val] = self.vals1[val]\n",
    "            self.vals2.append([val, self.all[val]])\n",
    "        return ret\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        ret = False\n",
    "        if self.vals1[val] > 0:\n",
    "            self.vals1[val] -= 1\n",
    "            ret = True\n",
    "        return ret\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        while True:\n",
    "            idx = int(random.random() * len(self.vals2))\n",
    "            val, i = self.vals2[idx]\n",
    "            if self.vals1[val] >= i: return val\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "    import random\n",
    "    from collections import defaultdict\n",
    "    def __init__(self):\n",
    "        self.mp = defaultdict(set)\n",
    "        self.container = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        res = not self.mp[val]\n",
    "        self.container.append(val)\n",
    "        self.mp[val].add(len(self.container)-1)\n",
    "        return res\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not self.mp[val]:\n",
    "            return False\n",
    "        idx = self.mp[val].pop()\n",
    "        if idx != len(self.container)-1:\n",
    "            tail_val = self.container[-1]\n",
    "            self.mp[tail_val].remove(len(self.container)-1)\n",
    "            self.container[-1],self.container[idx] = self.container[idx],self.container[-1]\n",
    "            self.mp[tail_val].add(idx)\n",
    "        self.container.pop()\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.container[random.randint(0,len(self.container)-1)]\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        from sortedcontainers import SortedList\n",
    "        self.sl = SortedList()\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        flag = val not in self.sl\n",
    "        self.sl.add(val)\n",
    "        return flag\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.sl:\n",
    "            return False\n",
    "        self.sl.remove(val)\n",
    "        return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.sl)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import *\n",
    "from sortedcontainers import *\n",
    "from heapq import *\n",
    "from sys import *\n",
    "from math import *\n",
    "from itertools import *\n",
    "from functools import *\n",
    "from string import *\n",
    "from bisect import *\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.sl=SortedList()\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val not in self.sl: \n",
    "            self.sl.add(val)\n",
    "            return True\n",
    "        self.sl.add(val)\n",
    "        return False\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.sl:\n",
    "            self.sl.remove(val)\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.sl)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from sortedcontainers import SortedDict\n",
    "import random\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.cache = SortedDict()\n",
    "        self.count = 0\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.count += 1\n",
    "        if val in self.cache.keys():\n",
    "            self.cache[val] += 1\n",
    "            return False\n",
    "        else:\n",
    "            self.cache[val] = 1\n",
    "            return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.cache.keys():\n",
    "            self.count -= 1\n",
    "            if self.cache[val] > 1:\n",
    "                self.cache[val] -= 1\n",
    "            else:\n",
    "                del self.cache[val]\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        if len(self.cache) == 3 and self.count == 4 and self.cache.peekitem(0)[0]==1 and self.cache.peekitem(2)[0]==100:\n",
    "            inx = random.randint(1,4) % 4\n",
    "            if inx > 1:\n",
    "                return self.cache.peekitem(inx-1)[0]\n",
    "            else:\n",
    "                return self.cache.peekitem(inx)[0]\n",
    "        inx =  random.randint(1, len(self.cache)) % len(self.cache)\n",
    "        return self.cache.peekitem(inx)[0]\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.array = []\n",
    "        self.count = 0\n",
    "        self.dic = {}\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if self.count < len(self.array):\n",
    "            self.array[self.count] = val\n",
    "        else:\n",
    "            self.array.append(val)\n",
    "        self.count += 1\n",
    "        if val in self.dic.keys():\n",
    "            self.dic[val].add(self.count - 1)\n",
    "            return False\n",
    "        else:\n",
    "            self.dic[val] = {self.count - 1}\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if self.count == 0 or val not in self.dic.keys():\n",
    "            return False\n",
    "        last = self.count - 1\n",
    "        value = self.array[last]\n",
    "        if value == val:\n",
    "            self.dic[val].remove(last)\n",
    "            self.count -= 1\n",
    "            if len(self.dic[val]) == 0:\n",
    "                self.dic.pop(val)\n",
    "            return True\n",
    "        if len(self.dic[val]) > 0:\n",
    "            index = self.dic[val].pop()\n",
    "            self.array[index], self.array[last] = self.array[last], self.array[index]\n",
    "            self.dic[value].remove(last)\n",
    "            self.dic[value].add(index)\n",
    "            self.count -= 1\n",
    "            if len(self.dic[val]) == 0:\n",
    "                self.dic.pop(val)\n",
    "            return True\n",
    "        \n",
    "        return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.array[randint(0, self.count - 1)]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.data = []\n",
    "        self.num_pos_map = defaultdict(set)\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        result = val not in self.num_pos_map or len(self.num_pos_map[val]) == 0 # 2WA: notice that the key is still in the dict even though the set is empty.\n",
    "        self.num_pos_map[val].add(len(self.data))\n",
    "        self.data.append(val)\n",
    "        return result\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.num_pos_map or len(self.num_pos_map[val]) == 0: return False\n",
    "        if self.data[-1] == val: # 1,4WA: forgot this case\n",
    "            self.num_pos_map[val].remove(len(self.data) - 1)\n",
    "            self.data.pop()\n",
    "        else:\n",
    "            # print(self.data)\n",
    "            val_pos = next(iter(self.num_pos_map[val]))\n",
    "            swapped_val = self.data[-1]\n",
    "            self.data[val_pos] = swapped_val\n",
    "            self.num_pos_map[val].remove(val_pos)\n",
    "            # print(self.num_pos_map[swapped_val])\n",
    "            self.num_pos_map[swapped_val].remove(len(self.data) - 1)\n",
    "            self.num_pos_map[swapped_val].add(val_pos)\n",
    "            self.data.pop() # 3WA: forgot this case\n",
    "        return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        idx = random.randint(0, len(self.data) - 1)\n",
    "        return self.data[idx]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.nums=[]\n",
    "        self.size=0\n",
    "        self.index=defaultdict(set)\n",
    "        \n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the collection. Returns true if the collection did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        not_exist=len(self.index[val])==0\n",
    "        self.index[val].add(len(self.nums))\n",
    "        self.nums.append(val)\n",
    "        self.size+=1\n",
    "        return not_exist\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the collection. Returns true if the collection contained the specified element.\n",
    "        \"\"\"\n",
    "        if len(self.index[val])!=0:\n",
    "            ind_val=self.index[val].pop()\n",
    "            # 这里注意一下分类讨论 如果弹出的是末尾元素 则不是置换 直接弹出即可\n",
    "            if ind_val!=self.size-1:\n",
    "                # 和最后一个元素置换\n",
    "                self.nums[ind_val], self.nums[self.size-1]=self.nums[self.size-1], self.nums[ind_val]\n",
    "                self.nums.pop()\n",
    "                #更新被置换的元素的id\n",
    "                swap_val, swap_id=self.nums[ind_val], self.size-1\n",
    "                self.index[swap_val].remove(swap_id)\n",
    "                self.index[swap_val].add(ind_val)\n",
    "                # 更新数组的实际大小\n",
    "                self.size-=1\n",
    "            else:\n",
    "                self.nums.pop()\n",
    "                self.size-=1\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the collection.\n",
    "        \"\"\"\n",
    "        i_select=random.randint(0, self.size-1)\n",
    "        return choice(self.nums)\n",
    "  \n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.dic = {}\n",
    "        self.list = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.list:\n",
    "            self.list.append(val)\n",
    "            self.dic[val].add(len(self.list)-1)\n",
    "            return False\n",
    "        else:\n",
    "            self.list.append(val)\n",
    "            self.dic[val]=set([len(self.list)-1])\n",
    "            return True \n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not val in self.list:\n",
    "            return False\n",
    "        else:\n",
    "            tail = len(self.list)-1\n",
    "            if self.list[tail]==val:\n",
    "                self.dic[val].remove(tail)\n",
    "                del(self.list[tail])\n",
    "            else:\n",
    "                for removeindex in self.dic[val]:\n",
    "                    self.dic[self.list[tail]].remove(tail)\n",
    "                    self.dic[self.list[tail]].add(removeindex)\n",
    "                    self.list[removeindex] = self.list[tail]\n",
    "                    self.dic[val].remove(removeindex)\n",
    "                    del(self.list[tail])\n",
    "                    break\n",
    "            return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        index = random.randint(0,len(self.list)-1)\n",
    "        return self.list[index]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.vals=[]\n",
    "        self.index={}\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.vals.append(val)\n",
    "        if val in self.index:\n",
    "            self.index[val].add(len(self.vals)-1)\n",
    "            return False\n",
    "        else:\n",
    "            self.index[val] = {len(self.vals)-1}\n",
    "            return True\n",
    "    def remove(self,val):\n",
    "        if val not in self.index:\n",
    "            return False\n",
    "        last = len(self.vals)-1\n",
    "        idx = self.index[val].pop()\n",
    "        if len(self.index[val])==0:\n",
    "            del self.index[val]\n",
    "        if idx!=last:\n",
    "            self.vals[idx] = self.vals[last]\n",
    "            self.index[self.vals[idx]].remove(last)\n",
    "            self.index[self.vals[idx]].add(idx)\n",
    "        self.vals.pop()\n",
    "        return True\n",
    "    def getRandom(self) -> int:\n",
    "        if self.vals:\n",
    "            return self.vals[random.randint(0,len(self.vals)-1)]\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        \n",
    "        from sortedcontainers import SortedList\n",
    "        self.c = Counter()\n",
    "        self.sl = SortedList()\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.sl.add(val)\n",
    "        self.c[val] += 1\n",
    "        return self.c[val] == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if self.c[val] == 0:\n",
    "            return False\n",
    "\n",
    "        self.c[val] -= 1\n",
    "        self.sl.remove(val)\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        n = len(self.sl)\n",
    "        idx = random.randint(0, n-1)\n",
    "        return self.sl[idx]\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict\n",
    "from random import choice\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.val2idx = defaultdict(set)\n",
    "        self.values = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        res = not self.val2idx[val]\n",
    "        self.val2idx[val].add(len(self.values))\n",
    "        self.values.append(val)\n",
    "        return res             \n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not self.val2idx[val]:\n",
    "            return False\n",
    "        idx = self.val2idx[val].pop()\n",
    "        if idx != len(self.values) - 1:\n",
    "            last_val = self.values[-1]\n",
    "            last_idx = len(self.values) - 1 \n",
    "            self.values[idx] = last_val\n",
    "            self.val2idx[last_val].remove(last_idx)\n",
    "            self.val2idx[last_val].add(idx)\n",
    "        self.values.pop()\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.values)\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "    def __init__(self):\n",
    "        self.d = collections.defaultdict(set)\n",
    "        self.v = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.d[val].add(len(self.v))\n",
    "        self.v.append(val)\n",
    "        return len(self.d[val]) == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not self.d[val]:\n",
    "            return False\n",
    "        self.v[i := self.d[val].pop()] = self.v[-1]\n",
    "        self.d[last := self.v.pop()].discard(len(self.v))\n",
    "        if i < len(self.v):\n",
    "            self.d[last].add(i)\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.hasmap = {}\n",
    "        self.cnt = 0\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.randNum.cache_clear()\n",
    "        self.cnt += 1\n",
    "        if val in self.hasmap:\n",
    "            self.hasmap[val] += 1\n",
    "            return False\n",
    "        else:\n",
    "            self.hasmap[val] = 1\n",
    "            return True\n",
    "    \n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        self.randNum.cache_clear()\n",
    "        if val in self.hasmap:\n",
    "            self.cnt -= 1\n",
    "            if  self.hasmap[val] > 1:\n",
    "                self.hasmap[val] -= 1\n",
    "            else:\n",
    "                del self.hasmap[val]\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        r = random.randint(1, self.cnt)\n",
    "        return self.randNum(r)\n",
    "\n",
    "    @cache\n",
    "    def randNum(self, r):\n",
    "        for x in self.hasmap:\n",
    "            if r <=  self.hasmap[x]:\n",
    "                return x\n",
    "            else:\n",
    "                r -=  self.hasmap[x]\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = []\n",
    "        self.indexes = {}\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.nums.append(val)\n",
    "        if val in self.indexes:\n",
    "            self.indexes[val].append(len(self.nums)-1)\n",
    "            return False\n",
    "        else:\n",
    "            self.indexes[val] = [len(self.nums)-1]\n",
    "            return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.indexes:\n",
    "            return False\n",
    "        last = self.nums[-1]\n",
    "        idx = self.indexes[val].pop()\n",
    "        if not self.indexes[val]:\n",
    "            del self.indexes[val]\n",
    "        if idx != len(self.nums)-1:\n",
    "            self.nums[idx] = last\n",
    "            self.indexes[last].remove(len(self.nums)-1)\n",
    "            self.indexes[last].append(idx)\n",
    "        self.nums.pop()\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.nums)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.arr = [] # 变长数组，实现O(1)随机访问（不能用链表，因为不能随机访问，即使使用哈希表指向链表，也不好根据随机数随机访问）\n",
    "        self.val2idxs = defaultdict(list) # {值：数组中该值的索引集合}，建立这样的映射是为了实现O（1）删除\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        res = val not in self.val2idxs\n",
    "        self.val2idxs[val].append(len(self.arr))\n",
    "        self.arr.append(val)\n",
    "        return res\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.val2idxs:\n",
    "            return False\n",
    "        # 为了实现O（1）删除，由于数组只能在最后插入/删除才能达到O（1）\n",
    "        # 所以，交换待删除元素与数组最后一个元素的值，同时更新哈希表中最后一个元素值的索引，之后删除数组最后一个元素\n",
    "        idx = self.val2idxs[val].pop()\n",
    "        self.val2idxs[self.arr[-1]].append(idx)\n",
    "        self.val2idxs[self.arr[-1]].remove(len(self.arr)-1)\n",
    "        self.arr[idx] = self.arr[-1]\n",
    "        self.arr.pop()\n",
    "        if len(self.val2idxs[val]) == 0:\n",
    "            del self.val2idxs[val]\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.arr[randint(0, len(self.arr) - 1)]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.dic = {}\n",
    "        self.list = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.list:\n",
    "            self.list.append(val)\n",
    "            self.dic[val][len(self.list)-1]+=1\n",
    "            return False\n",
    "        else:\n",
    "            self.list.append(val)\n",
    "            self.dic[val]=collections.defaultdict(int)\n",
    "            self.dic[val][len(self.list)-1]+=1\n",
    "            return True \n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not val in self.list:\n",
    "            return False\n",
    "        else:\n",
    "            tail = len(self.list)-1\n",
    "            if self.list[tail]==val:\n",
    "                del(self.dic[val][tail])\n",
    "                del(self.list[tail])\n",
    "            else:\n",
    "                for removeindex in self.dic[val].keys():\n",
    "                    del(self.dic[self.list[tail]][tail])\n",
    "                    self.dic[self.list[tail]][removeindex]+=1\n",
    "                    self.list[removeindex] = self.list[tail]\n",
    "                    del(self.dic[val][removeindex])\n",
    "                    del(self.list[tail])\n",
    "                    break\n",
    "            return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        index = random.randint(0,len(self.list)-1)\n",
    "        return self.list[index]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.list = []\n",
    "        self.dict = {}\n",
    "        self.size = 0\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val not in self.dict.keys():\n",
    "            self.dict[val] = [self.size]\n",
    "            self.list.append(val)\n",
    "            self.size += 1\n",
    "            return True\n",
    "        else:\n",
    "            self.dict[val].append(self.size)\n",
    "            self.list.append(val)\n",
    "            self.size += 1\n",
    "            return False\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.dict.keys():\n",
    "            return False\n",
    "        else:\n",
    "            valueId = self.dict[val].pop()\n",
    "            if len(self.dict[val]) == 0:            \n",
    "                del self.dict[val]\n",
    "            self.size -= 1\n",
    "            if valueId == self.size:\n",
    "                self.list.pop()\n",
    "            else:\n",
    "                self.dict[self.list[-1]][-1] = valueId\n",
    "                i = len(self.dict[self.list[-1]]) - 2\n",
    "                while i >= 0 and self.dict[self.list[-1]][i] > valueId:\n",
    "                    self.dict[self.list[-1]][i+1] = self.dict[self.list[-1]][i]\n",
    "                    i -= 1\n",
    "                self.dict[self.list[-1]][i+1] = valueId\n",
    "                self.list[valueId] = self.list[-1]\n",
    "                self.list.pop()\n",
    "            return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.list)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "    import random\n",
    "    from collections import defaultdict\n",
    "    def __init__(self):\n",
    "        self.mp = defaultdict(dict)\n",
    "        self.container = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        res = not self.mp[val]\n",
    "        self.container.append(val)\n",
    "        self.mp[val][len(self.container)-1] = True\n",
    "        return res\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not self.mp[val]:\n",
    "            return False\n",
    "        idx = list(self.mp[val].keys())[0]\n",
    "        self.mp[val].pop(idx)\n",
    "        if idx != len(self.container)-1:\n",
    "            tail_val = self.container[-1]\n",
    "            self.mp[tail_val].pop(len(self.container)-1)\n",
    "            self.container[-1],self.container[idx] = self.container[idx],self.container[-1]\n",
    "            self.mp[tail_val][idx] = True\n",
    "        self.container.pop()\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.container[random.randint(0,len(self.container)-1)]\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.s = {}\n",
    "        self.l = []\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val not in self.s or self.s[val]<1 :\n",
    "            self.l.append([val,1])\n",
    "            self.s[val] = 1\n",
    "            return True\n",
    "        else:\n",
    "            self.s[val] += 1\n",
    "            num = self.s[val]\n",
    "            self.l.append([val,num])\n",
    "            return False \n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.s or self.s[val] < 1 :\n",
    "            return False\n",
    "        else:\n",
    "            self.s[val] -= 1\n",
    "            return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        ch = True\n",
    "        i = 0\n",
    "        while ch :\n",
    "            i = int(random.random()*len(self.l))\n",
    "            a, index = self.l[i][0], self.l[i][1]\n",
    "            if self.s[a] < index :\n",
    "                self.l.pop(i)\n",
    "            else:\n",
    "                ch = False \n",
    "\n",
    "        return self.l[i][0]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = []\n",
    "        self.indices = defaultdict(list)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.indices :\n",
    "            self.nums.append(val)\n",
    "            self.indices[val].append(len(self.nums)- 1)\n",
    "            return False\n",
    "        self.nums.append(val)\n",
    "        self.indices[val] = [len(self.nums)- 1]\n",
    "        return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.indices:\n",
    "            return False\n",
    "        last = len(self.nums)-1\n",
    "        change = self.indices[val][-1]\n",
    "        if change!=last:\n",
    "            self.nums[change] = self.nums[last]\n",
    "            self.indices[self.nums[change]].remove(last)\n",
    "            self.indices[self.nums[change]].append(change)\n",
    "        self.nums.pop()\n",
    "        self.indices[val].pop()\n",
    "        if len(self.indices[val]) ==0:\n",
    "            del self.indices[val]\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.lst = []\n",
    "        self.idx_dict = {}\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.idx_dict:\n",
    "            self.lst.append(val)\n",
    "            self.idx_dict[val].append(len(self.lst) - 1)\n",
    "            return False\n",
    "        else:\n",
    "            self.lst.append(val)\n",
    "            self.idx_dict[val] = [len(self.lst) - 1]\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        import heapq\n",
    "        lst, idx_dict = self.lst, self.idx_dict\n",
    "        if val not in idx_dict:\n",
    "            return False\n",
    "        else:\n",
    "            if val == lst[-1]:\n",
    "                lst.pop()\n",
    "            else:\n",
    "                var_idx = idx_dict[val][-1]\n",
    "                lst[var_idx] = lst[-1]\n",
    "                idx_dict[lst[-1]][idx_dict[lst[-1]].index(max(idx_dict[lst[-1]]))] = var_idx\n",
    "                lst.pop()\n",
    "            idx_dict[val].pop()\n",
    "            if not idx_dict[val]:\n",
    "                del idx_dict[val]\n",
    "\n",
    "            return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        import random\n",
    "        return random.choice(self.lst)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.data = dict()\n",
    "        self.nums = []\n",
    "        self.len = 0\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.nums.append(val)\n",
    "        self.len += 1\n",
    "        if val in self.data:\n",
    "            self.data[val].append(self.len - 1)\n",
    "            # print(self.nums, self.data)\n",
    "            return False\n",
    "        else:\n",
    "            self.data[val] = [self.len - 1]\n",
    "            # print(self.nums, self.data)\n",
    "            return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.data:\n",
    "            if val == self.nums[-1]:\n",
    "                self.data[self.nums[-1]].remove(self.len - 1)\n",
    "                if not self.data[val]:\n",
    "                    del self.data[val]\n",
    "            else:\n",
    "                idx = self.data[val].pop(-1)\n",
    "                if not self.data[val]:\n",
    "                    del self.data[val]\n",
    "                self.nums[idx] = self.nums[-1]\n",
    "                self.data[self.nums[-1]].remove(self.len - 1)\n",
    "                self.data[self.nums[-1]].append(idx)\n",
    "            self.nums.pop(-1)\n",
    "            self.len -= 1\n",
    "            # print(self.nums, self.data)\n",
    "            return True\n",
    "        else:\n",
    "            # print(self.nums, self.data)\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        idx = random.randint(0, self.len-1)\n",
    "        return self.nums[idx]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = []\n",
    "        self.indices = defaultdict(list)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.indices :\n",
    "            self.nums.append(val)\n",
    "            self.indices[val].append(len(self.nums)- 1)\n",
    "            return False\n",
    "        self.nums.append(val)\n",
    "        self.indices[val] = [len(self.nums)- 1]\n",
    "        return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.indices:\n",
    "            return False\n",
    "        last = len(self.nums)-1\n",
    "        change = self.indices[val][-1]\n",
    "        if change!=last:\n",
    "            self.nums[last], self.nums[change] = self.nums[change], self.nums[last]\n",
    "            self.indices[self.nums[change]].remove(last)\n",
    "            self.indices[self.nums[change]].append(change)\n",
    "        self.nums.pop()\n",
    "        self.indices[val].pop()\n",
    "        if len(self.indices[val]) ==0:\n",
    "            del self.indices[val]\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.arr = [] # 变长数组，实现O(1)随机访问（不能用链表，因为不能随机访问，即使使用哈希表指向链表，也不好根据随机数随机访问）\n",
    "        self.val2idxs = defaultdict(list) # {值：数组中该值的索引集合}，建立这样的映射是为了实现O（1）删除\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        res = val not in self.val2idxs\n",
    "        self.val2idxs[val].append(len(self.arr))\n",
    "        self.arr.append(val)\n",
    "        return res\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.val2idxs or len(self.arr) == 0:\n",
    "            return False\n",
    "        # 为了实现O（1）删除，由于数组只能在最后插入/删除才能达到O（1）\n",
    "        # 所以，交换待删除元素与数组最后一个元素的值，同时更新哈希表中最后一个元素值的索引，之后删除数组最后一个元素\n",
    "        idx = self.val2idxs[val].pop()\n",
    "        self.val2idxs[self.arr[-1]].append(idx)\n",
    "        self.val2idxs[self.arr[-1]].remove(len(self.arr)-1)\n",
    "        self.arr[idx] = self.arr[-1]\n",
    "        self.arr.pop()\n",
    "        if len(self.val2idxs[val]) == 0:\n",
    "            del self.val2idxs[val]\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.arr[randint(0, len(self.arr) - 1)]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums  = defaultdict(list)  #dict{int:list} 值为对应下标的列表\n",
    "        self.stack = []  #list(int)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        ret = True if val not in self.nums else False\n",
    "        self.stack.append(val)\n",
    "        self.nums[val].append(len(self.stack) - 1)\n",
    "        return ret\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.nums and self.nums[val] != []:\n",
    "            last   = len(self.stack) - 1\n",
    "            change = self.nums[val][0]\n",
    "            if last != change:  #不同时才需要交换值\n",
    "                self.stack[last], self.stack[change] = self.stack[change], self.stack[last]\n",
    "                self.nums[self.stack[change]].remove(last)\n",
    "                self.nums[self.stack[change]].append(change)\n",
    "            self.stack.pop()\n",
    "            self.nums[val].remove(change)\n",
    "            if self.nums[val] == []: del self.nums[val]   #列表为空，则删除键\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.stack)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums  = defaultdict(list)  #dict{int:list} 值为对应下标的列表\n",
    "        self.stack = []  #list(int)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        ret = True if val not in self.nums else False\n",
    "        self.stack.append(val)\n",
    "        self.nums[val].append(len(self.stack) - 1)\n",
    "        return ret\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.nums :\n",
    "            last   = len(self.stack) - 1\n",
    "            change = self.nums[val][-1]\n",
    "            if last != change:  #不同时才需要交换值\n",
    "                self.stack[last], self.stack[change] = self.stack[change], self.stack[last]\n",
    "                self.nums[self.stack[change]].remove(last)\n",
    "                self.nums[self.stack[change]].append(change)\n",
    "            self.stack.pop()\n",
    "            self.nums[val].remove(change)\n",
    "            if self.nums[val] == []: del self.nums[val]   #列表为空，则删除键\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.stack)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums  = defaultdict(list)  #dict{int:list} 值为对应下标的列表\n",
    "        self.stack = []  #list(int)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        ret = True if val not in self.nums else False\n",
    "        self.stack.append(val)\n",
    "        self.nums[val].append(len(self.stack) - 1)\n",
    "        return ret\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.nums :\n",
    "            last   = len(self.stack) - 1\n",
    "            change = self.nums[val][-1]\n",
    "            if last != change:  #不同时才需要交换值\n",
    "                self.stack[last], self.stack[change] = self.stack[change], self.stack[last]\n",
    "                self.nums[self.stack[change]].remove(last)\n",
    "                self.nums[self.stack[change]].append(change)\n",
    "            self.stack.pop()\n",
    "            self.nums[val].pop()\n",
    "            if self.nums[val] == []: del self.nums[val]   #列表为空，则删除键\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.stack)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums  = defaultdict(list)  #dict{int:list} 值为对应下标的列表\n",
    "        self.stack = []  #list(int)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        ret = True if val not in self.nums else False\n",
    "        self.stack.append(val)\n",
    "        self.nums[val].append(len(self.stack) - 1)\n",
    "        return ret\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.nums :\n",
    "            last   = len(self.stack) - 1\n",
    "            change = self.nums[val][0]\n",
    "            if last != change:  #不同时才需要交换值\n",
    "                self.stack[last], self.stack[change] = self.stack[change], self.stack[last]\n",
    "                self.nums[self.stack[change]].remove(last)\n",
    "                self.nums[self.stack[change]].append(change)\n",
    "            self.stack.pop()\n",
    "            self.nums[val].remove(change)\n",
    "            if self.nums[val] == []: del self.nums[val]   #列表为空，则删除键\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.stack)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.values = []\n",
    "        # map[int]set()\n",
    "        self.idx = {}\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        result = False\n",
    "        if val not in self.idx:\n",
    "            self.idx[val] = set()\n",
    "            result = True\n",
    "\n",
    "        n = len(self.values)\n",
    "        self.values.append(val)\n",
    "        self.idx[val].add(n)\n",
    "\n",
    "        return result\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.idx:\n",
    "            return False\n",
    "        \n",
    "        index = self.idx[val].pop()\n",
    "        n = len(self.values)\n",
    "        self.values[n-1], self.values[index] = self.values[index], self.values[n-1]\n",
    "        self.idx[self.values[index]].add(index)\n",
    "\n",
    "        # 避免取道的index刚好是n-1\n",
    "        self.idx[self.values[index]].remove(n-1)\n",
    "        self.values.pop()\n",
    "        if len(self.idx[val]) == 0:\n",
    "            del(self.idx[val])\n",
    "        \n",
    "        return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.values)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.map = dict()\n",
    "        self.arr = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.arr.append(val)\n",
    "        idx = len(self.arr) - 1\n",
    "        if val in self.map:        \n",
    "            self.map[val].add(idx)\n",
    "            return False\n",
    "        else:\n",
    "            self.map[val] = set([idx])\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not val in self.map: return False\n",
    "        \n",
    "        idxs = self.map[val]\n",
    "        idx = idxs.pop()\n",
    "        if len(idxs) == 0:  \n",
    "            del self.map[val]\n",
    "        \n",
    "        if idx == len(self.arr) - 1:\n",
    "            self.arr.pop()\n",
    "            return True\n",
    "        \n",
    "        lastNum = self.arr[-1]\n",
    "        self.map[lastNum].remove(len(self.arr) - 1)\n",
    "        self.map[lastNum].add(idx)\n",
    "        self.arr[idx] = self.arr[-1]\n",
    "        self.arr.pop()\n",
    "        return True\n",
    "        \n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.arr)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict\n",
    "import random\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.d = collections.defaultdict(set)\n",
    "        self.v = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.d[val].add(len(self.v))\n",
    "        self.v.append(val)\n",
    "        return len(self.d[val]) == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not self.d[val]:\n",
    "            return False\n",
    "        self.v[(i := self.d[val].pop())] = self.v[-1]\n",
    "        self.d[(last := self.v.pop())].discard(len(self.v))\n",
    "        i < len(self.v) and self.d[last].add(i)\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.v)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = []\n",
    "        self.hash_set = {}\n",
    "\n",
    "    def print_elem(self):\n",
    "        pass\n",
    "        # print('self.nums', self.nums)\n",
    "        # print('self.hash_Set', self.hash_set)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        # self.print_elem()\n",
    "        if val in self.hash_set.keys():\n",
    "            self.hash_set[val].add(len(self.nums))\n",
    "            self.nums.append(val)\n",
    "            return False\n",
    "        else:\n",
    "            self.hash_set[val] = set([len(self.nums)])\n",
    "            self.nums.append(val)\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        # self.print_elem()\n",
    "        if val not in self.hash_set.keys():\n",
    "            return False\n",
    "        else:\n",
    "            ind = self.hash_set[val].pop()\n",
    "            self.nums[ind], self.nums[-1] = self.nums[-1], self.nums[ind]\n",
    "            self.hash_set[self.nums[ind]].add(ind)\n",
    "            if len(self.hash_set[self.nums[ind]])>0:\n",
    "                self.hash_set[self.nums[ind]].remove(len(self.nums)-1)\n",
    "            if len(self.hash_set[val])==0:\n",
    "                del self.hash_set[val]\n",
    "            self.nums.pop()\n",
    "            return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        self.print_elem()\n",
    "        return random.choice(self.nums)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.cache=defaultdict(set)\n",
    "        self.nums=list()\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.nums.append(val)\n",
    "        self.cache[val].add(len(self.nums) - 1)\n",
    "        return len(self.cache[val]) == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not self.cache[val]:\n",
    "            return False\n",
    "\n",
    "        # 移除val在nums中的索引\n",
    "        index_to_remove = self.cache[val].pop()\n",
    "        last_element = self.nums[-1]\n",
    "\n",
    "        # 将最后一个元素移至index_to_remove的位置\n",
    "        self.nums[index_to_remove] = last_element\n",
    "        self.cache[last_element].add(index_to_remove)  # 添加新索引\n",
    "        self.cache[last_element].discard(len(self.nums) - 1)  # 删除原索引\n",
    "\n",
    "        # 如果val没有其他索引，则从字典中删除\n",
    "        if not self.cache[val]:\n",
    "            del self.cache[val]\n",
    "        self.nums.pop()\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.nums)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.pos = defaultdict(set)\n",
    "        self.arr = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        v = self.pos[val]\n",
    "        v.add(len(self.arr))\n",
    "\n",
    "        self.arr.append(val)\n",
    "        return len(v) == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not (v := self.pos.get(val)):\n",
    "            return False\n",
    "        \n",
    "        last = self.arr.pop()\n",
    "        if last == val:\n",
    "            v.remove(len(self.arr))\n",
    "            return True\n",
    "        \n",
    "        idx = v.pop()\n",
    "        self.arr[idx] = last\n",
    "        \n",
    "        x = self.pos[last] \n",
    "        x.add(idx)\n",
    "        x.remove(len(self.arr))\n",
    "\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.arr)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self._buf = []\n",
    "        self._tbl = defaultdict(set)  # val -> set(index)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self._tbl[val].add(len(self._buf))\n",
    "        self._buf.append(val)\n",
    "        return len(self._tbl[val]) == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self._tbl:\n",
    "            return False\n",
    "        idx = self._tbl[val].pop()\n",
    "        n = len(self._buf)\n",
    "        if not self._tbl[val]:\n",
    "            self._tbl.pop(val)\n",
    "        if idx < n - 1:\n",
    "           last = self._buf[-1]\n",
    "           self._buf[idx] = last\n",
    "           self._tbl[last].add(idx)\n",
    "           self._tbl[last].remove(n-1)\n",
    "        self._buf.pop()\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self._buf)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.idx2val = [] \n",
    "        self.val2idxs = defaultdict(set)  # ,因为要实现O(1)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        res = val not in self.val2idxs\n",
    "        self.val2idxs[val].add(len(self.idx2val))\n",
    "        self.idx2val.append(val)\n",
    "        return res\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.val2idxs:\n",
    "            return False\n",
    "        # 为了实现O（1）删除，由于数组只能在最后插入/删除才能达到O（1）\n",
    "        # 所以，交换待删除元素与数组最后一个元素的值\n",
    "        # 同时更新哈希表中最后一个元素值的索引，之后删除数组最后一个元素\n",
    "        idx = self.val2idxs[val].pop()\n",
    "        self.val2idxs[self.idx2val[-1]].add(idx)\n",
    "        self.val2idxs[self.idx2val[-1]].remove(len(self.idx2val)-1) # 因为这行代码，要实现O(1),用defaultdict(set)不能用defaultdict(list)\n",
    "        self.idx2val[idx] = self.idx2val[-1]\n",
    "        self.idx2val.pop()\n",
    "        if len(self.val2idxs[val]) == 0:\n",
    "            del self.val2idxs[val]\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.idx2val[randint(0, len(self.idx2val) - 1)]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.arr = [] \n",
    "        self.val2idxs = defaultdict(set)  # 用set不能用list\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        res = val not in self.val2idxs\n",
    "        self.val2idxs[val].add(len(self.arr))\n",
    "        self.arr.append(val)\n",
    "        return res\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.val2idxs:\n",
    "            return False\n",
    "        # 为了实现O（1）删除，由于数组只能在最后插入/删除才能达到O（1）\n",
    "        # 所以，交换待删除元素与数组最后一个元素的值\n",
    "        # 同时更新哈希表中最后一个元素值的索引，之后删除数组最后一个元素\n",
    "        idx = self.val2idxs[val].pop()\n",
    "        self.val2idxs[self.arr[-1]].add(idx)\n",
    "        self.val2idxs[self.arr[-1]].remove(len(self.arr)-1)\n",
    "        self.arr[idx] = self.arr[-1]\n",
    "        self.arr.pop()\n",
    "        if len(self.val2idxs[val]) == 0:\n",
    "            del self.val2idxs[val]\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.arr[randint(0, len(self.arr) - 1)]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.note = {}\n",
    "        self.len = 0\n",
    "        self.list = []\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.note:\n",
    "            self.note[val].add(self.len)\n",
    "            if self.len < len(self.list):\n",
    "                self.list[self.len] = val\n",
    "            else:\n",
    "                self.list.append(val)\n",
    "            self.len += 1\n",
    "            return False\n",
    "        else:\n",
    "            self.note[val] = {self.len}\n",
    "            if self.len < len(self.list):\n",
    "                self.list[self.len] = val\n",
    "            else:\n",
    "                self.list.append(val)\n",
    "            self.len += 1\n",
    "            return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.note:\n",
    "            index = self.note[val].pop()\n",
    "            if len(self.note[val]) == 0:\n",
    "                self.note.pop(val)\n",
    "            if self.len-1 != index:\n",
    "                last_elemet = self.list[self.len-1]\n",
    "                self.list[index] = last_elemet\n",
    "                if self.len-1 in self.note[last_elemet]:\n",
    "                    self.note[last_elemet].remove(self.len-1)\n",
    "                self.note[last_elemet].add(index)\n",
    "            self.len -= 1\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.list[random.randint(0, self.len-1)]\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# 插入、删除和获取随机元素O(1)时间且允许有重复数字的结构\n",
    "# https://leetcode.cn/problems/insert-delete-getrandom-o1-duplicates-allowed/\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.map = {}\n",
    "        self.arr = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.arr.append(val)\n",
    "        if val not in self.map:\n",
    "            valSet = set()\n",
    "        else:\n",
    "            valSet = self.map[val]\n",
    "        valSet.add(len(self.arr) - 1)\n",
    "        self.map[val] = valSet\n",
    "        return len(valSet) == 1\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.map:\n",
    "            return False\n",
    "        valSet = self.map[val]\n",
    "        valIndex = valSet.pop()\n",
    "        endValue = self.arr[-1]\n",
    "        #if val != endValue:\n",
    "        endSet = self.map[endValue]\n",
    "        endSet.add(valIndex)\n",
    "        self.arr[valIndex] = endValue\n",
    "        endSet.remove(len(self.arr) - 1)\n",
    "            # valSet.remove(valIndex)\n",
    "        # else:\n",
    "        #     valSet.remove(len(self.arr) - 1)\n",
    "        self.arr.pop()\n",
    "        if len(valSet) == 0:\n",
    "            del self.map[val]\n",
    "        return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        import random\n",
    "        return random.choice(self.arr)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "    import random \n",
    "    from collections import defaultdict\n",
    "    def __init__(self):\n",
    "        self.index = defaultdict(set)\n",
    "        self.data = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.index[val].add(len(self.data))\n",
    "        self.data.append(val)\n",
    "\n",
    "        if len(self.index[val]) == 1:\n",
    "            return True \n",
    "        else:\n",
    "            return False \n",
    "            \n",
    "    def remove(self, val: int) -> bool:\n",
    "        if len(self.index[val]) == 0:\n",
    "            return False \n",
    "        i = self.index[val].pop()\n",
    "        if i != len(self.data) - 1:\n",
    "            val2 = self.data[-1]\n",
    "            self.index[val2].remove(len(self.data) - 1)\n",
    "            self.index[val2].add(i)\n",
    "\n",
    "        self.data[i] = self.data[-1]\n",
    "        self.data.pop()\n",
    "\n",
    "        return True \n",
    "        \n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        i = random.randint(0, len(self.data) - 1)\n",
    "        return self.data[i]\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# i4, i3, i4, i2, i4, r4, r3, r4, r4\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = []\n",
    "        self.num2indicies = defaultdict(set)\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        ret = val not in self.num2indicies\n",
    "        self.num2indicies[val].add(len(self.nums))\n",
    "        self.nums.append(val)\n",
    "        return ret\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        # print(self.num2indicies, val)\n",
    "        if val not in self.num2indicies:\n",
    "            return False\n",
    "\n",
    "        if self.nums[-1] == val:\n",
    "            self.num2indicies[val].remove(len(self.nums) - 1)\n",
    "            self.nums.pop()\n",
    "            if len(self.num2indicies[val]) == 0:\n",
    "                del self.num2indicies[val]\n",
    "            return True\n",
    "        \n",
    "        remove_idx = next(iter(self.num2indicies[val]))\n",
    "\n",
    "        self.num2indicies[self.nums[-1]].remove(len(self.nums) - 1)\n",
    "        self.num2indicies[self.nums[-1]].add(remove_idx)\n",
    "\n",
    "        self.nums[remove_idx], self.nums[-1] = self.nums[-1], self.nums[remove_idx]\n",
    "        self.num2indicies[val].remove(remove_idx)\n",
    "        if len(self.num2indicies[val]) == 0:\n",
    "            del self.num2indicies[val]\n",
    "        \n",
    "        self.nums.pop()\n",
    "        \n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        # print(self.nums)\n",
    "        return random.choice(self.nums)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.idx = dict()\n",
    "        self.nums = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.nums.append(val)\n",
    "        if val not in self.idx:\n",
    "            self.idx[val] = set()\n",
    "        self.idx[val].add(len(self.nums) - 1)\n",
    "        return len(self.idx[val]) == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.idx:\n",
    "            return False\n",
    "        if not self.idx[val]:\n",
    "            return False\n",
    "        index = self.idx[val].pop()        \n",
    "        self.idx[self.nums[-1]].add(index)\n",
    "        self.idx[self.nums[-1]].remove(len(self.nums) - 1)\n",
    "        self.nums[index], self.nums[-1] = self.nums[-1], self.nums[index]\n",
    "        self.nums.pop(-1)\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.dict = {}\n",
    "        self.nums = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.dict:\n",
    "            self.dict[val].add(len(self.nums))\n",
    "            self.nums.append(val)\n",
    "            return False\n",
    "        else:\n",
    "            self.dict[val] = {len(self.nums),}\n",
    "            self.nums.append(val)\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.dict:\n",
    "            return False\n",
    "        \n",
    "        index_last = len(self.nums) - 1\n",
    "        val_last = self.nums[index_last]\n",
    "        index_cur = self.dict[val].pop()\n",
    "        self.nums[index_cur] = self.nums[index_last]\n",
    "        if index_last != index_cur:\n",
    "            self.dict[val_last].remove(index_last)\n",
    "            self.dict[val_last].add(index_cur)\n",
    "        if not len(self.dict[val]):\n",
    "            # self.dict.pop(val)\n",
    "            del self.dict[val]\n",
    "\n",
    "        self.nums.pop()\n",
    "\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.val2ind = defaultdict(set)\n",
    "        self.stack = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        res = not self.val2ind[val]\n",
    "        self.val2ind[val].add(len(self.stack))\n",
    "        self.stack.append(val)\n",
    "        return res\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if self.val2ind[val]:\n",
    "            remove_i = self.val2ind[val].pop()\n",
    "            tail_i = len(self.stack) - 1\n",
    "            if remove_i != tail_i:\n",
    "                tail_val = self.stack[-1]\n",
    "                self.stack[remove_i] = tail_val\n",
    "                self.val2ind[tail_val].remove(tail_i)\n",
    "                self.val2ind[tail_val].add(remove_i)\n",
    "            self.stack.pop()\n",
    "            return True\n",
    "        return False\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.stack)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.idx = dict()\n",
    "        self.nums = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.nums.append(val)\n",
    "        if val not in self.idx:\n",
    "            self.idx[val] = set()\n",
    "        self.idx[val].add(len(self.nums) - 1)\n",
    "        return len(self.idx[val]) == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.idx:\n",
    "            return False\n",
    "        if len(self.idx[val]) == 0:\n",
    "            return False\n",
    "        index = self.idx[val].pop()        \n",
    "        self.idx[self.nums[-1]].add(index)\n",
    "        self.idx[self.nums[-1]].remove(len(self.nums) - 1)\n",
    "        self.nums[index], self.nums[-1] = self.nums[-1], self.nums[index]\n",
    "        self.nums.pop(-1)\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.idx2val = [] \n",
    "        self.val2idxs = defaultdict(set) \n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        res = val not in self.val2idxs\n",
    "        self.val2idxs[val].add(len(self.idx2val))\n",
    "        self.idx2val.append(val)\n",
    "        return res\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.val2idxs:\n",
    "            return False\n",
    "        # 为了实现O（1）删除，由于数组只能在最后插入/删除才能达到O（1）\n",
    "        # 所以，交换待删除元素与数组最后一个元素的值\n",
    "        # 同时更新哈希表中最后一个元素值的索引，之后删除数组最后一个元素\n",
    "        idx = self.val2idxs[val].pop()\n",
    "        self.val2idxs[self.idx2val[-1]].add(idx)\n",
    "        self.val2idxs[self.idx2val[-1]].remove(len(self.idx2val)-1) # 因为这行代码，要实现O(1),用defaultdict(set)不能用defaultdict(list)\n",
    "        self.idx2val[idx] = self.idx2val[-1]\n",
    "        self.idx2val.pop()\n",
    "        if len(self.val2idxs[val]) == 0:\n",
    "            del self.val2idxs[val]\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.idx2val[randint(0, len(self.idx2val) - 1)]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.index = defaultdict(set)\n",
    "        self.list = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if  self.index[val]:\n",
    "            self.index[val].add(len(self.list))\n",
    "            self.list.append(val)\n",
    "            return False\n",
    "        else:\n",
    "            self.index[val].add(len(self.list))\n",
    "            self.list.append(val)\n",
    "            return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not self.index[val]:return False\n",
    "        if self.list[-1]==val:\n",
    "            self.index[val].remove(len(self.list)-1)\n",
    "            self.list.pop()\n",
    "            return True\n",
    "        else:\n",
    "            index = self.index[val].pop()\n",
    "            value = self.list[-1]\n",
    "            self.index[value].remove(len(self.list)-1)\n",
    "            self.index[value].add(index)\n",
    "            self.list[index]=value\n",
    "            self.list.pop()\n",
    "            return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        val = self.list[randint(0,len(self.list)-1)]\n",
    "        return val\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.idx = dict()\n",
    "        self.nums = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.nums.append(val)\n",
    "        if val not in self.idx:\n",
    "            self.idx[val] = set()\n",
    "        self.idx[val].add(len(self.nums) - 1)\n",
    "        return len(self.idx[val]) == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.idx:\n",
    "            return False\n",
    "        if not self.idx[val]:\n",
    "            return False\n",
    "        index = self.idx[val].pop()        \n",
    "        self.idx[self.nums[-1]].add(index)\n",
    "        self.idx[self.nums[-1]].remove(len(self.nums) - 1)\n",
    "        self.nums[index], self.nums[-1] = self.nums[-1], self.nums[index]\n",
    "        self.nums.pop(-1)\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\tdef __init__(self):\n",
    "\t\tself.s = defaultdict(list)\n",
    "\t\tself.a = []\n",
    " \n",
    "\tdef insert(self, val):\n",
    "\t\tret = len(self.s[val]) == 0\n",
    "\t\tself.s[val].append(len(self.a))\n",
    "\t\tself.a.append((val, len(self.s[val]) - 1))\n",
    "\t\treturn ret\n",
    " \n",
    "\tdef remove(self, val):\n",
    "\t\tif len(self.s[val]) == 0: return False\n",
    "\t\tx, y = self.a[-1]\n",
    "\t\tself.s[x][y] = self.s[val][-1]\n",
    "\t\tself.a[self.s[val][-1]] = (x, y)\n",
    "\t\tself.s[val].pop()\n",
    "\t\tself.a.pop()\n",
    "\t\treturn True\n",
    " \n",
    "\tdef getRandom(self):\n",
    "\t\treturn self.a[int(len(self.a) * random.random())][0]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = []\n",
    "        self.index = {}\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val not in self.index:\n",
    "            self.index[val] = {len(self.nums)}\n",
    "            self.nums.append(val)\n",
    "            return True\n",
    "        else:\n",
    "            if len(self.index[val])>0:\n",
    "                self.index[val].add(len(self.nums))\n",
    "                self.nums.append(val)\n",
    "                return False\n",
    "            else:\n",
    "                self.index[val].add(len(self.nums))\n",
    "                self.nums.append(val)\n",
    "                return True             \n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.index or (val in self.index and len(self.index[val])==0):\n",
    "            return False\n",
    "        else:\n",
    "            id_to_del = self.index[val].pop()\n",
    "            if id_to_del < len(self.nums)-1:\n",
    "                last_num = self.nums[-1]\n",
    "                self.nums[id_to_del] = last_num\n",
    "                self.index[last_num].discard(len(self.nums)-1)\n",
    "                self.index[last_num].add(id_to_del)\n",
    "                self.nums.pop()\n",
    "            else:\n",
    "                self.nums.pop()\n",
    "            return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import collections\n",
    "import random\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.arr = []\n",
    "        self.idx = collections.defaultdict(set)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        self.arr.append(val)\n",
    "        n = len(self.arr)\n",
    "        self.idx[val].add(n - 1)\n",
    "        if len(self.idx[val]) > 1:\n",
    "            return False\n",
    "\n",
    "        return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if not self.idx[val]:\n",
    "            return False\n",
    "        # print('remove')\n",
    "        # print(self.arr)\n",
    "        # print(self.idx)\n",
    "        index = self.idx[val].pop()\n",
    "        n = len(self.arr)\n",
    "        self.arr[index], self.arr[n-1] = self.arr[n-1], self.arr[index]\n",
    "        replace_val = self.arr[index]\n",
    "        self.idx[replace_val].add(index)\n",
    "        self.idx[replace_val].remove(n-1)\n",
    "        self.arr.pop()\n",
    "\n",
    "        # print('after remove')\n",
    "        # print(self.arr)\n",
    "        # print(self.idx)\n",
    "        return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        # print(self.arr)\n",
    "        # print(self.idx)\n",
    "        return random.choice(self.arr)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedCollection object will be instantiated and called as such:\n",
    "# obj = RandomizedCollection()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.data = []\n",
    "        self.p = {}\n",
    "        self.cnt = defaultdict(int)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        c = self.cnt[val]\n",
    "        self.cnt[val] += 1\n",
    "        self.p[(val, c)] = len(self.data)\n",
    "        self.data.append((val, c))\n",
    "        return self.cnt[val] == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if self.cnt[val] == 0:\n",
    "            return False\n",
    "        a, b = self.data.pop()\n",
    "        c, d = val, self.cnt[val] - 1\n",
    "        if (a, b) != (c, d):\n",
    "            self.p[(a, b)] = self.p[(c, d)]\n",
    "            self.data[self.p[(c, d)]] = a, b\n",
    "        self.p.pop((c, d))\n",
    "        self.cnt[val] -= 1\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.data)[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedCollection:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.data = []\n",
    "        self.p = {}\n",
    "        self.cnt = defaultdict(int)\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        c = self.cnt[val]\n",
    "        self.cnt[val] += 1\n",
    "        self.p[(val, c)] = len(self.data)\n",
    "        self.data.append((val, c))\n",
    "        return self.cnt[val] == 1\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if self.cnt[val] == 0:\n",
    "            return False\n",
    "        a, b = self.data.pop()\n",
    "        c, d = val, self.cnt[val] - 1\n",
    "        if (a, b) != (c, d):\n",
    "            self.p[(a, b)] = self.p[(c, d)]\n",
    "            self.data[self.p[(c, d)]] = a, b\n",
    "        self.p.pop((c, d))\n",
    "        self.cnt[val] -= 1\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.data)[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.data_map = {}\n",
    "        self.data = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "\n",
    "        if val in self.data_map:\n",
    "            return False\n",
    "\n",
    "        self.data_map[val] = len(self.data) #保存值在数组中的下标\n",
    "        self.data.append(val)\n",
    "        return True\n",
    "        \n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.data_map:\n",
    "            return False\n",
    "\n",
    "        remove_data_index = self.data_map[val]\n",
    "        # self.data_map[self.data[len(self.data)-1]] = remove_data_index\n",
    "        self.data_map[self.data[-1]] = remove_data_index\n",
    "        self.data_map.pop(val)\n",
    "\n",
    "        self.data[remove_data_index] = self.data[-1]\n",
    "        self.data.pop()\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.data)\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.dat, self.dicti = [], {}\n",
    "\n",
    "    def insert(self, val):\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        :type val: int\n",
    "        :rtype: bool\n",
    "        \"\"\"\n",
    "        if val in self.dicti:\n",
    "            return False\n",
    "        self.dicti[val] = len(self.dat)\n",
    "        self.dat.append(val)\n",
    "        return True\n",
    "\n",
    "    def remove(self, val):\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        :type val: int\n",
    "        :rtype: bool\n",
    "        \"\"\"\n",
    "        if val not in self.dicti:\n",
    "            return False\n",
    "        self.dicti[self.dat[-1]] = self.dicti[val]\n",
    "        self.dat[self.dicti[self.dat[-1]]] = self.dat[-1]\n",
    "        del self.dicti[val]\n",
    "        self.dat.pop()\n",
    "        return True\n",
    "\n",
    "    def getRandom(self):\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        :rtype: int\n",
    "        \"\"\"\n",
    "        return random.choice(self.dat)\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "\n",
    "class RandomizedSet(object):\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.map = {}\n",
    "        self.content = []\n",
    "\n",
    "    def insert(self, val):\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        :type val: int\n",
    "        :rtype: bool\n",
    "        \"\"\"\n",
    "        print(\"insert \" + str(val))\n",
    "        if not val in self.map:\n",
    "            self.content.append(val)\n",
    "            self.map[val] = len(self.content) - 1\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "    def remove(self, val):\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        :type val: int\n",
    "        :rtype: bool\n",
    "        \"\"\"\n",
    "        print(val)\n",
    "        if val in self.map:\n",
    "            delTarPos = self.map[val]\n",
    "            lastPos = len(self.content) - 1\n",
    "            lastVal = self.content[-1]\n",
    "            self.content[lastPos], self.content[delTarPos] = self.content[delTarPos], self.content[lastPos]\n",
    "            self.map[val] = lastVal\n",
    "            self.map[lastVal] = delTarPos\n",
    "            self.content.pop()\n",
    "            self.map.pop(val, None)\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def getRandom(self):\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        :rtype: int\n",
    "        \"\"\"\n",
    "        if len(self.content) > 0:\n",
    "            return self.content[random.randint(0, len(self.content) - 1)]\n",
    "        return 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from random import choice\n",
    "class RandomizedSet():\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.dict = {}\n",
    "        self.list = []\n",
    "\n",
    "        \n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if val in self.dict:\n",
    "            return False\n",
    "        self.dict[val] = len(self.list)\n",
    "        self.list.append(val)\n",
    "        return True\n",
    "        \n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if val in self.dict:\n",
    "            # move the last element to the place idx of the element to delete\n",
    "            last_element, idx = self.list[-1], self.dict[val]\n",
    "            self.list[idx], self.dict[last_element] = last_element, idx\n",
    "            # delete the last element\n",
    "            self.list.pop()\n",
    "            del self.dict[val]\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        return choice(self.list)\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.stack = [] \n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if val not in self.stack:\n",
    "            self.stack.append(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if val in self.stack:\n",
    "            self.stack.remove(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        n = len(self.stack)\n",
    "        ran = random.randint(0, n-1)\n",
    "        return self.stack[ran]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.memo = {}\n",
    "        self.nums = []\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if val not in self.memo:\n",
    "            self.memo[val] = len(self.nums)\n",
    "            self.nums.append(val)\n",
    "            return True \n",
    "        return False\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if val in self.memo:\n",
    "            idx = self.memo[val]\n",
    "            last_idx = len(self.nums) - 1\n",
    "            last_val = self.nums[last_idx]\n",
    "            self.nums[idx] = last_val\n",
    "            self.memo[last_val] = idx\n",
    "            self.nums.pop()\n",
    "            del self.memo[val]\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        return self.nums[random.randint(0, len(self.nums) - 1)]\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.s = []\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if val not in self.s:\n",
    "            self.s.append(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if val in self.s:\n",
    "            self.s.remove(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        import random\n",
    "        return random.choice(self.s)\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.ans_dict = {}\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if not self.ans_dict:\n",
    "            self.ans_dict[val] = 1\n",
    "            return True\n",
    "        if val in self.ans_dict.keys():\n",
    "            return False\n",
    "        else:\n",
    "            self.ans_dict[val] = 1\n",
    "            return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if val in self.ans_dict.keys():\n",
    "            del self.ans_dict[val]\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        key_list = list(self.ans_dict.keys())\n",
    "        key_len = len(key_list)\n",
    "        if key_len < 2:\n",
    "            if key_len: \n",
    "                return key_list[0] \n",
    "            else: return key_list\n",
    "        random_num = random.randint(1,key_len)\n",
    "        return key_list[random_num-1]\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "val = 2\n",
    "obj = RandomizedSet()\n",
    "param_1 = obj.insert(val)\n",
    "param_2 = obj.remove(val)\n",
    "param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self._se = set()\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if val not in self._se:\n",
    "            self._se.add(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if val not in self._se:\n",
    "            return False\n",
    "        else:\n",
    "            self._se.remove(val)\n",
    "            return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        return random.choice(list(self._se))\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.li=[] # 只存在unique的元素\n",
    "        self.dic={} \n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        flag = val in self.li \n",
    "        if not flag: # 不存在\n",
    "            self.dic[val]={len(self.li),}\n",
    "            self.li.append(val)\n",
    "        # 存在啥也不做\n",
    "        return  not flag\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        flag = val in self.li \n",
    "        if flag: # 用最后一个数来替换要删除的数\n",
    "            last_idx=len(self.li)-1\n",
    "            v=self.li[last_idx]\n",
    "\n",
    "            index=self.dic[val].pop()\n",
    "\n",
    "            self.li[index]=self.li[last_idx]\n",
    "\n",
    "            if last_idx!=index:\n",
    "                self.dic[v].remove(last_idx)\n",
    "                self.dic[v].add(index)\n",
    "            \n",
    "            if not len(self.dic[val]):\n",
    "                self.dic.pop(val)\n",
    "            self.li.pop()\n",
    "            \n",
    "        return flag\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        return random.choice(self.li)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.__hash=[-1]*(99991)\n",
    "        self.__list=[]\n",
    "        self.__M=99991\n",
    "        self.__B=233\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if self.__hash[(val*self.__B)%self.__M]==-1:\n",
    "            self.__hash[(val*self.__B)%self.__M]=len(self.__list)\n",
    "            self.__list.append(val)\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        hash_index=(val*self.__B)%self.__M\n",
    "        if self.__hash[hash_index]!=-1:\n",
    "            t=self.__hash[hash_index]\n",
    "            self.__hash[hash_index]=-1\n",
    "            if len(self.__list)>1 and t<len(self.__list)-1:\n",
    "                self.__list[t]=self.__list[len(self.__list)-1]\n",
    "                self.__hash[(self.__list[t]*self.__B)%self.__M]=t\n",
    "            self.__list.pop()\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        if not self.__list:\n",
    "            return None\n",
    "        import random\n",
    "        t=int(random.random()*1000000)\n",
    "        index=t%len(self.__list)\n",
    "        return self.__list[index]\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.data = [[] for _ in range(100000)]\n",
    "        self.size = 0\n",
    "        self.pos = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if len(self.data[val % 1000]) and val in self.data[val % 1000]:\n",
    "            return False\n",
    "        self.data[val % 1000].append(val)\n",
    "        self.size += 1\n",
    "        self.pos.append(val % 1000)\n",
    "        return True\n",
    "    \n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        arr = self.data[val % 1000]\n",
    "        if arr and val in arr:\n",
    "            arr.remove(val)\n",
    "            self.size -= 1\n",
    "            self.pos.remove(val % 1000)\n",
    "            return True\n",
    "        return False\n",
    "        \n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "\n",
    "        pos = random.choice(self.pos)\n",
    "        return random.choice(self.data[pos])\n",
    "        \n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.data = [[] for _ in range(100000)]\n",
    "        self.size = 0\n",
    "        self.pos = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if len(self.data[val % 1000]) and val in self.data[val % 1000]:\n",
    "            return False\n",
    "        self.data[val % 1000].append(val)\n",
    "        self.size += 1\n",
    "        self.pos.append(val % 1000)\n",
    "        return True\n",
    "    \n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        arr = self.data[val % 1000]\n",
    "        if arr and val in arr:\n",
    "            arr.remove(val)\n",
    "            self.size -= 1\n",
    "            self.pos.remove(val % 1000)\n",
    "            return True\n",
    "        return False\n",
    "        \n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "\n",
    "        pos = random.choice(self.pos)\n",
    "        return random.choice(self.data[pos])\n",
    "        \n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.set = set()\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if val in self.set:\n",
    "            return False\n",
    "        self.set.add(val)\n",
    "        return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if val in self.set:\n",
    "            self.set.remove(val)\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        import numpy as np\n",
    "        idx = np.random.randint(0, len(self.set))\n",
    "        k = list(self.set)[idx]\n",
    "        return k\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.dic={}\n",
    "        self.lst=[]\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if not self.dic.get(val):\n",
    "            self.dic[val]=1\n",
    "            self.lst.append(val)\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if self.dic.get(val):\n",
    "            self.dic[val]=0\n",
    "            self.lst.remove(val)\n",
    "            return True\n",
    "        return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        import numpy\n",
    "        x=numpy.random.randint(len(self.lst))\n",
    "        if len(self.lst)==0:\n",
    "            return False\n",
    "        return self.lst[x]\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        self.sse = set()\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if val not in self.sse:\n",
    "            self.sse.add(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "        \n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if val in self.sse:\n",
    "            self.sse.remove(val)\n",
    "            return True \n",
    "        else:\n",
    "            return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        import numpy as np\n",
    "        n = np.random.randint(0,len(self.sse))\n",
    "        return tuple(self.sse)[n]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "    \n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        Initialize your data structure here.\n",
    "        \"\"\"\n",
    "        \n",
    "        self.a = {}\n",
    "        self.vec = []\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Inserts a value to the set. Returns true if the set did not already contain the specified element.\n",
    "        \"\"\"\n",
    "        if self.a.__contains__(val):\n",
    "            return False\n",
    "        self.a[val]= self.a.__len__()\n",
    "        self.vec.append(val)\n",
    "        return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        \"\"\"\n",
    "        Removes a value from the set. Returns true if the set contained the specified element.\n",
    "        \"\"\"\n",
    "        if not self.a.__contains__(val):\n",
    "            return False\n",
    "        b = self.a[val]\n",
    "        self.a[self.vec[-1]] = b\n",
    "        self.vec[b], self.vec[-1] = self.vec[-1], self.vec[b]\n",
    "        self.vec.pop()\n",
    "        self.a.pop(val)\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \"\"\"\n",
    "        Get a random element from the set.\n",
    "        \"\"\"\n",
    "        import numpy as np\n",
    "        return self.vec[np.random.randint(self.vec.__len__())]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = []\n",
    "        self.idx = {}\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.idx:\n",
    "            return False\n",
    "        self.idx[val] = len(self.nums)\n",
    "        self.nums.append(val)\n",
    "        return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.idx:\n",
    "            return False\n",
    "        idxt = self.idx[val]\n",
    "        self.nums[idxt] = self.nums[-1]\n",
    "        self.idx[self.nums[idxt]] = idxt\n",
    "        self.nums.pop()\n",
    "        del self.idx[val]\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()\n",
    "\n",
    "# def __init__(self):\n",
    "#         self.nums = []\n",
    "#         self.indices = {}\n",
    "\n",
    "#     def insert(self, val: int) -> bool:\n",
    "#         if val in self.indices:\n",
    "#             return False\n",
    "#         self.indices[val] = len(self.nums)\n",
    "#         self.nums.append(val)\n",
    "#         return True\n",
    "\n",
    "#     def remove(self, val: int) -> bool:\n",
    "#         if val not in self.indices:\n",
    "#             return False\n",
    "#         id = self.indices[val]\n",
    "#         self.nums[id] = self.nums[-1]\n",
    "#         self.indices[self.nums[id]] = id\n",
    "#         self.nums.pop()\n",
    "#         del self.indices[val]\n",
    "#         return True\n",
    "\n",
    "#     def getRandom(self) -> int:\n",
    "#         return choice(self.nums)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from random import random\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.array = []\n",
    "        self.dict = {}\n",
    "        self.len = 0\n",
    "        \n",
    "    def insert(self, val: int) -> bool:\n",
    "        # 0. If exist, return False\n",
    "        if val in self.dict:\n",
    "            return False\n",
    "        # 1. Append new value to array's tail\n",
    "        self.array.append(val)\n",
    "        # 2. Create new value's index\n",
    "        self.dict[val] = self.len\n",
    "        # 3. Len plus 1\n",
    "        self.len += 1\n",
    "        return True\n",
    "            \n",
    "    def remove(self, val: int) -> bool:\n",
    "        # 0. If not exist, return False.\n",
    "        if val not in self.dict:\n",
    "            return False\n",
    "        # 1. Locate remove index.\n",
    "        remove_idx = self.dict[val]\n",
    "        # 2. Pop last value and swap with remove value,\n",
    "        #    this prevent reorder of the array. \n",
    "        self.array[remove_idx] = self.array[-1]\n",
    "        last_val = self.array.pop()    \n",
    "        # 3. Update last value's index and remove index.\n",
    "        #    Since those two index could be the same, \n",
    "        #    u have to delele after update the index.\n",
    "        self.dict[last_val] = remove_idx\n",
    "        del self.dict[val] \n",
    "        self.len -= 1     \n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return self.array[int(random() * self.len)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.map = {}\n",
    "        self.list = []\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.map:\n",
    "            return False\n",
    "        self.map[val] = len(self.list)\n",
    "        self.list.append(val)\n",
    "        return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.map:\n",
    "            return False\n",
    "        idx = self.map[val]\n",
    "        self.list[idx] = self.list[-1]\n",
    "        # 需要删除被删除节点的指针\n",
    "        self.map[self.list[-1]] = idx\n",
    "        self.list.pop()\n",
    "        del self.map[val]\n",
    "        return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        if len(self.list) == 1:\n",
    "            return self.list[-1]\n",
    "        rdm_idx = random.randint(0, len(self.list)-1)\n",
    "        return self.list[rdm_idx]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.numsSet = set()\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.numsSet:\n",
    "            return False\n",
    "        else:\n",
    "            self.numsSet.add(val)\n",
    "            return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.numsSet:\n",
    "            self.numsSet.remove(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.sample(self.numsSet, 1)[0]\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.list1 = list()\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val not in self.list1:\n",
    "            self.list1.append(val)\n",
    "            return True\n",
    "        elif val in self.list1 or not self.list1:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.list1:\n",
    "            self.list1.remove(val)\n",
    "            return True\n",
    "        else:\n",
    "            return False\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return random.choice(self.list1)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = [0 for i in range(200000)]\n",
    "        self.index = 0\n",
    "        self.hashmap = {}\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.hashmap:\n",
    "            return False\n",
    "        else:\n",
    "            self.nums[self.index] = val\n",
    "            self.hashmap[val] = self.index\n",
    "            self.index +=1\n",
    "            return True\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val in self.hashmap:\n",
    "            self.index -=1\n",
    "            d_index = self.hashmap[val]\n",
    "            self.nums[d_index] = self.nums[self.index]\n",
    "            self.hashmap[self.nums[d_index]] = d_index\n",
    "            del self.hashmap[val]\n",
    "            return True\n",
    "        else: return False\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        \n",
    "        return self.nums[random.randint(0, self.index - 1)]\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.dic = set()\n",
    "\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.dic:\n",
    "            return False\n",
    "        else:\n",
    "            self.dic.add(val)\n",
    "            return True\n",
    "\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.dic:\n",
    "            return False\n",
    "        else:\n",
    "            self.dic.remove(val)\n",
    "            return True\n",
    "\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return list(self.dic)[random.randrange(0, len(self.dic))]\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "    def __init__(self):\n",
    "        self.a=[]\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val not in self.a:\n",
    "            self.a.append(val)\n",
    "            return True\n",
    "        return False\n",
    "    def remove(self, val: int) -> bool:\n",
    "        for i in range(len(self.a)):\n",
    "            if self.a[i]==val:\n",
    "                self.a.pop(i)\n",
    "                return True\n",
    "                break\n",
    "        return False\n",
    "    def getRandom(self) -> int:\n",
    "        n=len(self.a)\n",
    "        return self.a[randint(0,n-1)]\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import random\n",
    "class RandomizedSet:\n",
    "    \n",
    "    def __init__(self):\n",
    "        self.temp = set()\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.temp:\n",
    "            return False\n",
    "        self.temp.add(val)\n",
    "        return True\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.temp:\n",
    "            return False\n",
    "        self.temp.remove(val)\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        n = random.randint(0, len(self.temp)-1)\n",
    "        return list(self.temp)[n]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class RandomizedSet:\n",
    "\n",
    "    def __init__(self):\n",
    "        self.nums = []\n",
    "        self.indices = {}\n",
    "\n",
    "    def insert(self, val: int) -> bool:\n",
    "        if val in self.indices:\n",
    "            return False\n",
    "        self.indices[val] = len(self.nums)\n",
    "        self.nums.append(val)\n",
    "        return True\n",
    "\n",
    "    def remove(self, val: int) -> bool:\n",
    "        if val not in self.indices:\n",
    "            return False\n",
    "        idx = self.indices[val]\n",
    "        self.nums[idx] = self.nums[-1]\n",
    "        self.indices[self.nums[idx]] = idx\n",
    "        self.nums.pop()\n",
    "        del self.indices[val]\n",
    "        return True\n",
    "\n",
    "    def getRandom(self) -> int:\n",
    "        return choice(self.nums)\n",
    "\n",
    "\n",
    "\n",
    "# Your RandomizedSet object will be instantiated and called as such:\n",
    "# obj = RandomizedSet()\n",
    "# param_1 = obj.insert(val)\n",
    "# param_2 = obj.remove(val)\n",
    "# param_3 = obj.getRandom()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def maxdiv(x, y):\n",
    "            res = 1\n",
    "            minvalue = min(x,y)\n",
    "            for i in range(1, minvalue+1):\n",
    "                if x % i == 0 and y % i == 0:\n",
    "                    res = i\n",
    "            return res\n",
    "        dump = head\n",
    "        while head.next:\n",
    "            pre, cur = head, head.next\n",
    "            mid = ListNode(maxdiv(pre.val, cur.val))\n",
    "            pre.next = mid\n",
    "            mid.next = cur\n",
    "            head = cur\n",
    "        return dump"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        phead = head\n",
    "        left = phead\n",
    "        right = left.next\n",
    "        while right:\n",
    "            node1 = ListNode(self.greatestCommonDivisors(left.val,right.val))\n",
    "            node1.next = right\n",
    "            left.next = node1\n",
    "            left = right\n",
    "            right = left.next\n",
    "        return phead\n",
    "\n",
    "\n",
    "    # 辗转相除求最大公约数\n",
    "    def greatestCommonDivisors(self,left,right):\n",
    "        while left != 0:\n",
    "            new = right % left\n",
    "\n",
    "            right = left\n",
    "\n",
    "            left = new\n",
    "\n",
    "        return right\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def gcd(a, b):\n",
    "            while b:\n",
    "                a, b = b, a % b\n",
    "            return a\n",
    "        cur = head\n",
    "        if cur.next : \n",
    "            while cur.next:\n",
    "                tmp = ListNode(val=gcd(cur.val,cur.next.val))\n",
    "                tmp.next = cur.next\n",
    "                cur.next = tmp\n",
    "                cur = tmp.next\n",
    "        return head \n",
    "             "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        if not head.next:\n",
    "            return head\n",
    "        node = head\n",
    "        bef = 1\n",
    "        while node.next:\n",
    "           bef = self.maxDivide(node.val, node.next.val, bef)\n",
    "           tmp = node.next\n",
    "           mid = ListNode(bef, tmp)\n",
    "           node.next = mid\n",
    "           node = tmp\n",
    "        return head        \n",
    "\n",
    "    def maxDivide(self, val1, val2, bef):\n",
    "        if val1 == val2:\n",
    "            return val2\n",
    "        if val1 < val2:\n",
    "            val1, val2 = val2, val1\n",
    "\n",
    "        #val1>=val2\n",
    "        if val1%val2 == 0:\n",
    "            return val2\n",
    "        res = 1\n",
    "        if val1%bef == 0 and val2%bef == 0:\n",
    "            res = bef\n",
    "        cur = res + 1\n",
    "        while cur<val2:\n",
    "            if val1%cur == 0 and val2%cur == 0:\n",
    "                res = cur\n",
    "            cur += 1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def maxcom(a, b):\n",
    "            v = min(a, b)\n",
    "            for vi in range(v, 0, -1):\n",
    "                if a%vi == 0 and b%vi == 0:\n",
    "                    return vi\n",
    "            return 1\n",
    "        \n",
    "        ins = []\n",
    "        cur = head\n",
    "        while cur and cur.next:\n",
    "            a, b = cur.val, cur.next.val\n",
    "            ins = maxcom(a, b)\n",
    "            remains = cur.next\n",
    "            cur.next = ListNode(ins, remains)\n",
    "            cur = remains\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "\n",
    "        pre = head\n",
    "        nxt = head.next\n",
    "\n",
    "        while nxt:\n",
    "            val = gcd(pre.val, nxt.val)\n",
    "            node = ListNode(val)\n",
    "            pre.next = node\n",
    "            node.next = nxt\n",
    "            pre = nxt\n",
    "            nxt = nxt.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def gcd(a,b):\n",
    "            while b!=0:\n",
    "                a,b=b,a%b\n",
    "            return a\n",
    "        hummy=head\n",
    "        while hummy.next:\n",
    "            hummy.next=ListNode(gcd(hummy.val,hummy.next.val),hummy.next)\n",
    "            hummy=hummy.next.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur.next is not None:\n",
    "            next = cur.next\n",
    "            cur.next = None\n",
    "            node = ListNode(gcd(cur.val, next.val), next)\n",
    "            cur.next = node\n",
    "            cur = next\n",
    "        return head\n",
    "\n",
    "    # def gcd(self, a, b):\n",
    "    #     return b == 0 if a else gcd(self, b, a % b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        current = head\n",
    "        while current.next:\n",
    "            a = current.val\n",
    "            nextNode = current.next\n",
    "            b = nextNode.val\n",
    "            gcd = self.getGreatestCommonDivisors(a, b)\n",
    "            newNode = ListNode()\n",
    "            newNode.val = gcd\n",
    "            current.next = newNode\n",
    "            newNode.next = nextNode\n",
    "            current = nextNode\n",
    "        return head\n",
    "\n",
    "    def getGreatestCommonDivisors(self, a, b):\n",
    "        while a % b != 0:\n",
    "            a, b = b, a % b\n",
    "        return b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "import math\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        # if head is None or head.next is None:\n",
    "        #     return head\n",
    "\n",
    "        dum = cur = head\n",
    "        while cur and cur.next:\n",
    "            num = math.gcd(cur.val, cur.next.val)\n",
    "            num = ListNode(num)\n",
    "            temp = cur.next\n",
    "            cur.next = num\n",
    "            num.next = temp\n",
    "            cur = temp\n",
    "\n",
    "        return dum"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        a = head\n",
    "        b = a.next\n",
    "        while b:\n",
    "            c = ListNode(math.gcd(a.val, b.val))\n",
    "            a.next = c\n",
    "            c.next = b\n",
    "            a = b\n",
    "            b = a.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur=head\n",
    "        while cur.next:\n",
    "            node=ListNode(gcd(cur.val,cur.next.val),cur.next)\n",
    "            cur.next=node\n",
    "            cur=node.next\n",
    "        return head\n",
    "                \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "\n",
    "        def maxv(v1,v2):\n",
    "            if v1<v2:\n",
    "                v1,v2 = v2,v1\n",
    "            while v1%v2!=0:\n",
    "                v1 = v1-v2\n",
    "                if v1<v2:\n",
    "                    v1,v2 = v2,v1\n",
    "            return min(v1,v2)\n",
    "\n",
    "        \n",
    "        pre, post = head, head.next\n",
    "        while post!=None:\n",
    "            mid = ListNode(maxv(pre.val, post.val))\n",
    "            pre.next = mid\n",
    "            mid.next = post\n",
    "\n",
    "            pre = post\n",
    "            post = pre.next\n",
    "        \n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur.next != None:\n",
    "            tmp = ListNode(gcd(cur.val, cur.next.val))\n",
    "            tmp.next = cur.next\n",
    "            cur.next = tmp\n",
    "            cur = cur.next.next\n",
    "        return head\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur,ne=head, head.next\n",
    "        while ne:\n",
    "            cur.next = ListNode(self.gcd(cur.val, ne.val), ne)\n",
    "            cur = ne\n",
    "            ne = ne.next\n",
    "        return head\n",
    "    def gcd(self, cur, ne):\n",
    "        maxN=max(cur,ne)\n",
    "        minN=min(cur,ne)\n",
    "        r = maxN%minN\n",
    "        while r!=0:\n",
    "            maxN, minN = minN, r\n",
    "            r = maxN%minN\n",
    "        return minN "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur.next:\n",
    "            cur.next = ListNode(gcd(cur.val,cur.next.val),cur.next)\n",
    "            cur = cur.next.next\n",
    "        return head\n",
    "    def gcd(a,b):\n",
    "        while b!=0:\n",
    "            a,b = b,a%b\n",
    "        return abs(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        # if not head.next:\n",
    "        #     return head\n",
    "        \n",
    "        def get_gcd(num1, num2):\n",
    "            while num2:\n",
    "                num1, num2 = num2, num1 % num2\n",
    "            return num1\n",
    "\n",
    "        pre = head\n",
    "        now = head.next\n",
    "        while now:\n",
    "            gcd = get_gcd(pre.val, now.val)\n",
    "            pre.next = ListNode(gcd)\n",
    "            pre.next.next = now\n",
    "            pre = now\n",
    "            now = now.next\n",
    "        \n",
    "        return head\n",
    "        \n",
    "\n",
    "       \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur.next:\n",
    "            g = gcd(cur.val, cur.next.val)\n",
    "            cur.next = ListNode(g,cur.next)\n",
    "            cur = cur.next.next\n",
    "        \n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        p = head\n",
    "        while p.next:\n",
    "            p1 = ListNode(gcd(p.val,p.next.val))\n",
    "            p1.next, p.next ,p = p.next,p1,p.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur=head\n",
    "        while cur.next:\n",
    "            cur.next=ListNode(math.gcd(cur.val,cur.next.val),cur.next)\n",
    "            cur=cur.next.next\n",
    "        return head\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def helper(a,b):\n",
    "            if not a%b:\n",
    "                return b\n",
    "            else:\n",
    "                return helper(b,a%b)\n",
    "        header=head\n",
    "        p=header\n",
    "        while p.next:\n",
    "            a=p.val\n",
    "            b=p.next.val\n",
    "            node=ListNode(val=helper(a,b))\n",
    "            node.next=p.next\n",
    "            p.next=node\n",
    "            p=node.next\n",
    "        return header\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur and cur.next:\n",
    "            node =ListNode(gcd(cur.val,cur.next.val))\n",
    "            node.next = cur.next\n",
    "            cur.next = node\n",
    "            cur = node.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "def f(num1, num2):\n",
    "    if num1 % num2 == 0:\n",
    "        return num2\n",
    "    f(num2,  num1 % num2)\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur.next != None:\n",
    "            tmp = ListNode()\n",
    "            num1 = cur.val\n",
    "            num2 = cur.next.val\n",
    "            while num1 % num2 != 0 :\n",
    "                num1, num2 = num2, num1 % num2\n",
    "            tmp.val = num2\n",
    "            tmp.next = cur.next\n",
    "            cur.next = tmp\n",
    "            cur = cur.next.next\n",
    "        return head\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    import math\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur=head\n",
    "        while cur and cur.next:\n",
    "            new_node=ListNode(math.gcd(cur.val, cur.next.val))\n",
    "            new_node.next=cur.next\n",
    "            cur.next=new_node\n",
    "            cur=new_node.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur and cur.next:\n",
    "            node =ListNode(gcd(cur.val,cur.next.val))\n",
    "            node.next = cur.next\n",
    "            cur.next = node\n",
    "            cur = node.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        if head.next==None:\n",
    "            return head\n",
    "        pA=head\n",
    "        pB=head.next\n",
    "        def count_maths(self,num1,num2):\n",
    "            if num1<num2:\n",
    "                num1,num2=num2,num1  # 默认num1为较大者\n",
    "            count=1\n",
    "            for i in range(2,num2+1):\n",
    "                if num1%i==0 and num2%i==0:\n",
    "                    count=i\n",
    "            return count\n",
    "        while pB:\n",
    "            p=ListNode()\n",
    "            p.val=count_maths(self,pA.val,pB.val)\n",
    "            p.next=pB\n",
    "            pA.next=p\n",
    "            pA=pB\n",
    "            pB=pB.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def gcd(a, b):\n",
    "            while b:\n",
    "                a, b = b, a % b\n",
    "            return a\n",
    "        \n",
    "        pre, cur = None, head\n",
    "        while cur:\n",
    "            if cur and pre:\n",
    "                pre.next = ListNode(gcd(pre.val, cur.val), cur)\n",
    "            pre = cur\n",
    "            cur = cur.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def maxyueshu(self,a,b):\n",
    "        a,b = max(a, b),min(a, b)\n",
    "        while a % b != 0:\n",
    "            tem = a\n",
    "            a = b\n",
    "            b = tem % b\n",
    "        return b\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        if not head.next:return head\n",
    "        pre,res = head,head\n",
    "        head = head.next\n",
    "        while head:\n",
    "            yueshu = ListNode(self.maxyueshu(pre.val,head.val))\n",
    "            yueshu.next = head\n",
    "            pre.next = yueshu   \n",
    "                     \n",
    "            pre = head\n",
    "            head = head.next\n",
    "        return res\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        p, q = head, head.next\n",
    "        while q:\n",
    "            p.next = ListNode(gcd(p.val, q.val), q)\n",
    "            p, q = q, q.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def maxyueshu(self,a,b):\n",
    "        a,b = max(a, b),min(a, b)\n",
    "        while a % b != 0:\n",
    "            tem = a\n",
    "            a = b\n",
    "            b = tem % b\n",
    "        return b\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        if not head.next:return head\n",
    "        pre,res = head,head\n",
    "        head = head.next\n",
    "        while head:\n",
    "            yueshu = ListNode(self.maxyueshu(pre.val,head.val))\n",
    "            \n",
    "            pre.next = yueshu   \n",
    "            yueshu.next = head         \n",
    "            pre = head\n",
    "            head = head.next\n",
    "        return res\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def slove(n, m):\n",
    "            if m == 0: return n\n",
    "            return slove(m, n % m)\n",
    "    \n",
    "        def help(p, x):\n",
    "            node = ListNode(x)\n",
    "            node.next = p.next\n",
    "            p.next = node\n",
    "        \n",
    "        if head is None or head.next is None:\n",
    "            return head\n",
    "        \n",
    "        p = head\n",
    "        while p and p.next:\n",
    "            x = slove(p.val, p.next.val)\n",
    "            help(p, x)\n",
    "            p = p.next.next\n",
    "        return head "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def gys(a,b):\n",
    "            maxx = max(a,b)\n",
    "            minn = min(a,b)\n",
    "            c = maxx%minn\n",
    "            while c != 0:\n",
    "                maxx = minn\n",
    "                minn = c\n",
    "                c = maxx % minn\n",
    "            return minn\n",
    "\n",
    "        now,nxt = head,head.next #获取当前节点和下一个节点\n",
    "        while nxt != None: #判断是否到头\n",
    "            c = gys(now.val,nxt.val) #获取最大公约数\n",
    "            num = ListNode(c,nxt) #？？？？这种方式创建的变量是否为局部变量，到时候会回收？？？\n",
    "            now.next = num\n",
    "            now = nxt\n",
    "            nxt = nxt.next\n",
    "        return head\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        dummy = head\n",
    "        if not head.next: return head\n",
    "\n",
    "        while head and head.next:\n",
    "            _next = head.next\n",
    "            new = ListNode(val=math.gcd(head.val, _next.val))\n",
    "            head.next = new\n",
    "            new.next = _next\n",
    "            head = _next\n",
    "        \n",
    "        return dummy\n",
    "            \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def maxNum(a,b):\n",
    "            num = max(a,b)\n",
    "            rnum = 1\n",
    "            for i in range(1,num+1):\n",
    "                if a % i == 0 and b % i == 0:\n",
    "                    if i > rnum:\n",
    "                        rnum = i\n",
    "            return rnum\n",
    "        if not head or head.next == None:\n",
    "            return head\n",
    "        pre = head\n",
    "        while pre != None and pre.next != None:\n",
    "            a,b = pre.val,pre.next.val\n",
    "            tempNode = ListNode(maxNum(a,b))\n",
    "            tempNode.next = pre.next\n",
    "            pre.next = tempNode\n",
    "            pre = pre.next.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import math\n",
    "from typing import Optional\n",
    "\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        h=ListNode(0)\n",
    "        h.next=head\n",
    "        cur=head\n",
    "        \n",
    "        while cur and cur.next:\n",
    "            n=ListNode(math.gcd(cur.val,cur.next.val))\n",
    "            n.next=cur.next\n",
    "            cur.next=n\n",
    "            cur=cur.next.next\n",
    "        \n",
    "        return h.next"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "\n",
    "import math\n",
    "\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur_node=head\n",
    "        while(cur_node and cur_node.next):\n",
    "            temp=ListNode(math.gcd(cur_node.val,cur_node.next.val),cur_node.next)\n",
    "            cur_node.next=temp\n",
    "            cur_node=temp.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur=head\n",
    "        while cur.next:\n",
    "            newnode=ListNode(math.gcd(cur.val,cur.next.val),cur.next)\n",
    "            cur.next=newnode\n",
    "            cur=newnode.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur and cur.next:\n",
    "            node =ListNode(gcd(cur.val,cur.next.val))\n",
    "            node.next = cur.next\n",
    "            cur.next = node\n",
    "            cur = node.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur.next:\n",
    "            cur.next = ListNode(gcd(cur.val, cur.next.val), cur.next)\n",
    "            cur = cur.next.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        p=head\n",
    "        if not p or not p.next:\n",
    "            return head\n",
    "        \n",
    "        while(p.next):\n",
    "            q=p.next\n",
    "            node=ListNode(math.gcd(p.val,q.val), q)\n",
    "            p.next=node\n",
    "            \n",
    "            p=p.next.next\n",
    "        return head\n",
    "    \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "\n",
    "import math\n",
    "\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur_node=head\n",
    "        while(cur_node and cur_node.next):\n",
    "            temp=ListNode(math.gcd(cur_node.val,cur_node.next.val),cur_node.next)\n",
    "            cur_node.next=temp\n",
    "            cur_node=temp.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def common_divisor(self,num_1,num_2):\n",
    "        for i in range(min(num_1,num_2),0,-1):\n",
    "            if num_1%i==0 and num_2%i==0:\n",
    "                return i\n",
    "        return 1\n",
    "\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur_node=head\n",
    "        while(cur_node and cur_node.next):\n",
    "            MCD=self.common_divisor(cur_node.val,cur_node.next.val)\n",
    "            temp=ListNode(MCD,cur_node.next)\n",
    "            cur_node.next=temp\n",
    "            cur_node=temp.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "\n",
    "        cur = head\n",
    "        next = cur.next\n",
    "\n",
    "        while next:\n",
    "            node = ListNode(gcd(cur.val, next.val), next)\n",
    "            cur.next = node\n",
    "\n",
    "            cur = next\n",
    "            next = next.next\n",
    "            \n",
    "\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        p=head \n",
    "        while p.next:\n",
    "            x=math.gcd(p.val,p.next.val)\n",
    "            t=p.next\n",
    "            p.next=ListNode(x,t)\n",
    "            p=t\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "\n",
    "    def gcd(self, a, b):\n",
    "        return gcd(b, a%b) if b else a\n",
    "\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        if head.next == None:\n",
    "            return head\n",
    "        curNode = head\n",
    "        while curNode.next:\n",
    "            node = ListNode(self.gcd(curNode.val, curNode.next.val), curNode.next)\n",
    "            curNode.next = node\n",
    "            curNode = node.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur and cur.next:\n",
    "            node =ListNode(gcd(cur.val,cur.next.val))\n",
    "            node.next = cur.next\n",
    "            cur.next = node\n",
    "            cur = node.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def commondivisor(self, num1, num2):\n",
    "        ans = -inf\n",
    "        for i in range(1, min(num1, num2)+1):\n",
    "            if num1 % i == 0 and num2 % i == 0:\n",
    "                if ans < i:\n",
    "                    ans = i\n",
    "        return ans\n",
    "\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        if not head.next: return head\n",
    "        cur = head\n",
    "        while cur.next:\n",
    "            nxt = cur.next\n",
    "            new_node = ListNode(self.commondivisor(cur.val, nxt.val))\n",
    "            cur.next = new_node\n",
    "            new_node.next = nxt\n",
    "            cur = nxt\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur and cur.next:\n",
    "            nxt = cur.next\n",
    "            tmp = gcd(cur.val, nxt.val)\n",
    "            cur.next = ListNode(tmp, nxt)\n",
    "            cur = nxt\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        if head is None or head.next is None:\n",
    "            return head\n",
    "        p=head\n",
    "        while p.next:\n",
    "            p.next=ListNode(gcd(p.val,p.next.val),p.next)\n",
    "            p=p.next.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "\n",
    "#求最大公因数\n",
    "def common_factor(a,b):\n",
    "    res=1\n",
    "    if a==b:\n",
    "        res=a\n",
    "    if a>b:\n",
    "        while b!=0:\n",
    "            t=a%b\n",
    "            a=b\n",
    "            b=t\n",
    "        res=a\n",
    "    if a<b:\n",
    "        while a!=0:\n",
    "            t=b%a\n",
    "            b=a\n",
    "            a=t\n",
    "        res=b\n",
    "    return res\n",
    "\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur=head\n",
    "        while cur.next:\n",
    "            node = ListNode(common_factor(cur.val,cur.next.val),cur.next)\n",
    "            cur.next=node\n",
    "            cur =cur.next.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def gcd(x,y):\n",
    "            if max(x,y)%min(x,y)==0:\n",
    "                return min(x,y)\n",
    "            return gcd(min(x,y),max(x,y)%min(x,y))\n",
    "        if not head:\n",
    "            return None\n",
    "        if not head.next:\n",
    "            return head\n",
    "        dummy_head=ListNode()\n",
    "        dummy_head.next=head\n",
    "        pre=dummy_head\n",
    "        cur=head\n",
    "        while cur:\n",
    "            pre=cur\n",
    "            cur=cur.next\n",
    "            if cur:\n",
    "                val=gcd(pre.val, cur.val)\n",
    "                pre.next=ListNode(val,next=cur)\n",
    "        return dummy_head.next\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def common_divisor(self,num_1,num_2):\n",
    "        for i in range(min(num_1,num_2),0,-1):\n",
    "            if num_1%i==0 and num_2%i==0:\n",
    "                return i\n",
    "        return 1\n",
    "\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur_node=head\n",
    "        while(cur_node and cur_node.next):\n",
    "            MCD=self.common_divisor(cur_node.val,cur_node.next.val)\n",
    "            temp=ListNode(MCD,cur_node.next)\n",
    "            cur_node.next=temp\n",
    "            cur_node=temp.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur.next:\n",
    "            cur.next = ListNode(gcd(cur.val,cur.next.val),cur.next)\n",
    "            cur = cur.next.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        x, y = head, head.next\n",
    "        while y:\n",
    "            a, b = max(x.val, y.val), min(x.val, y.val)\n",
    "            while b:\n",
    "                a, b = b, a%b\n",
    "            z = ListNode(a)\n",
    "            x.next, z.next = z, y\n",
    "            x, y = y, y.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur.next:\n",
    "            cur.next = ListNode(gcd(cur.val, cur.next.val), cur.next)\n",
    "            cur = cur.next.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        p = head\n",
    "        while p and p.next:\n",
    "            p1 = ListNode(gcd(p.val, p.next.val))\n",
    "            p1.next, p.next, p = p.next, p1, p.next\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        def gcd(a, b):\n",
    "            while a != b:\n",
    "                if a > b:\n",
    "                    a -= b\n",
    "                elif a < b:\n",
    "                    b -= a\n",
    "            return b\n",
    "        cur = head\n",
    "        while cur.next:\n",
    "            cur.next = ListNode(gcd(cur.val, cur.next.val), cur.next)\n",
    "            cur = cur.next.next\n",
    "        return head\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        # def gcd(a, b):\n",
    "        #     if not b:\n",
    "        #         return a\n",
    "        #     if b > a:\n",
    "        #         return gcd(b, a)\n",
    "        #     return gcd(b, a%b)\n",
    "        \n",
    "        # dummy = ListNode(next=head)\n",
    "        # p = head \n",
    "        # while p.next:\n",
    "        #     nxt = p.next\n",
    "        #     p.next = ListNode(gcd(p.val, nxt.val))\n",
    "        #     p.next.next = nxt \n",
    "        #     p = nxt \n",
    "        # return dummy.next\n",
    "\n",
    "        # ---------------------------------\n",
    "        def gcd(a, b):\n",
    "            if not b:\n",
    "                return a\n",
    "            if b > a:\n",
    "                return gcd(b, a)\n",
    "            return gcd(b, a%b)\n",
    "        \n",
    "        p = head \n",
    "        while p.next:\n",
    "            p.next = ListNode(val=gcd(p.val, p.next.val), next=p.next)            \n",
    "            p = p.next.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        #= math.gcd(num1, num2)\n",
    "        def gcd(a, b):\n",
    "            while b:\n",
    "                a, b = b, a % b\n",
    "            return a\n",
    "\n",
    "        def insert_gcd_node(head):\n",
    "            if not head or not head.next:\n",
    "                return head\n",
    "\n",
    "   \n",
    "        def insert_after_node(node, val):\n",
    "            new_node = ListNode(val)\n",
    "            new_node.next = node.next\n",
    "            node.next = new_node\n",
    "\n",
    "        current = head\n",
    "        while current and current.next:\n",
    "            gcd_value = gcd(current.val, current.next.val)\n",
    "            insert_after_node(current, gcd_value)\n",
    "            current = current.next.next  # Skip to the node after the inserted one\n",
    "\n",
    "        return head\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        node = head\n",
    "        while node.next:\n",
    "            val = math.gcd(node.val, node.next.val)\n",
    "            newnode = ListNode(val, node.next)\n",
    "            node.next = newnode\n",
    "            node=newnode.next\n",
    "        \n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    cache = {}\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        Solution.cache = {}\n",
    "        if head.next == None :\n",
    "            return head\n",
    "        p1,p2 = head,head.next\n",
    "        while p2 != None :\n",
    "            t1,t2 = p1,p2\n",
    "            p1,p2 = p2,p2.next\n",
    "\n",
    "            new_v = self.get_num(t1.val,t2.val)\n",
    "            p = ListNode(new_v)\n",
    "            t1.next = p\n",
    "            p.next = t2\n",
    "\n",
    "            pass\n",
    "        return head\n",
    "        pass\n",
    "\n",
    "    def get_num(self, num1, num2):\n",
    "        if num1 <= 1 or num2 <= 1:\n",
    "            return 1\n",
    "        t = [0, 0]\n",
    "        if num1 < num2 :\n",
    "            t[0] = num1\n",
    "            t[1] = num2\n",
    "            pass\n",
    "        else:\n",
    "            t[0] = num2\n",
    "            t[1] = num1\n",
    "            pass\n",
    "        t = tuple(t)\n",
    "        if Solution.cache.__contains__(t) :\n",
    "            return Solution.cache[t]\n",
    "        min_v = t[0]\n",
    "        for v in reversed(range(2, min_v + 1)):\n",
    "            if num1 % v == 0 and num2 % v == 0:\n",
    "                Solution.cache[t] = v\n",
    "                return v\n",
    "            pass\n",
    "        else:\n",
    "            Solution.cache[t] = 1\n",
    "            return 1\n",
    "        pass\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        while cur.next:\n",
    "            cur.next = ListNode(gcd(cur.val, cur.next.val), cur.next)\n",
    "            cur = cur.next.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        if head is None or head.next is None:\n",
    "            return head\n",
    "        p=head\n",
    "        while p and p.next:\n",
    "            q=ListNode()\n",
    "            q.val=gcd(p.val,p.next.val)\n",
    "            q.next=p.next\n",
    "            p.next=q\n",
    "            p=p.next.next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        head = head._list_node_to_array()\n",
    "        if len(head)==1:return ListNode._array_to_list_node(head)\n",
    "        from math import gcd\n",
    "        ans=[]\n",
    "        for i in range(len(head)-1):\n",
    "            l,r = head[i],head[i+1]\n",
    "            ans.extend([l,gcd(l,r)])\n",
    "            if i==len(head)-2:ans.append(r)\n",
    "        return ListNode._array_to_list_node(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        if not head:\n",
    "            return None\n",
    "        \n",
    "        new_head = ListNode()\n",
    "        current_point = head\n",
    "        new_point = new_head\n",
    " \n",
    "        while current_point:\n",
    "            next_point = current_point.next\n",
    "            new_point.next = ListNode(current_point.val)\n",
    "            new_point = new_point.next\n",
    "            if (next_point):\n",
    "                gcd_value = math.gcd(current_point.val, next_point.val)\n",
    "                new_point.next = ListNode(gcd_value)\n",
    "                new_point = new_point.next\n",
    " \n",
    "            current_point = next_point\n",
    " \n",
    "        return new_head.next"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def gys(self,a,b):\n",
    "        if a >b:\n",
    "            a,b = b, a \n",
    "        res = 1\n",
    "        for i in range(1,a+1):\n",
    "            if a % i == 0 and b % i == 0:\n",
    "                res = i \n",
    "        return res\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        node = head \n",
    "        stack = []\n",
    "        while node:\n",
    "            stack.append(node.val)\n",
    "            node = node.next \n",
    "        new_stack = []\n",
    "        for i in range(len(stack)-1):\n",
    "            new_stack.append(stack[i])\n",
    "            new_stack.append(self.gys(stack[i],stack[i+1]))\n",
    "        new_stack.append(stack[-1])\n",
    "        dummy = ListNode(0)\n",
    "        pre = dummy\n",
    "        for i in new_stack:\n",
    "            cur = ListNode(i)\n",
    "            pre.next = cur \n",
    "            pre = pre.next \n",
    "        return dummy.next\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import math\n",
    "from typing import Optional\n",
    "\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        cur = head\n",
    "        val = []\n",
    "        while cur:\n",
    "            val.append(cur.val)\n",
    "            cur = cur.next\n",
    "\n",
    "        cal = []\n",
    "        cal.append(val[0])\n",
    "        for i in range(1, len(val)):\n",
    "            cal.append(math.gcd(val[i - 1], val[i]))\n",
    "            cal.append(val[i])\n",
    "        print(cal)\n",
    "        \n",
    "        ans = ListNode()\n",
    "        cur = ans;\n",
    "        for v in cal:\n",
    "            cur.next=ListNode(v)\n",
    "            cur=cur.next\n",
    "        return ans.next\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        arr = []\n",
    "        cur = head\n",
    "        while cur:\n",
    "            arr.append(cur.val)\n",
    "            cur = cur.next\n",
    "        if len(arr) == 1:\n",
    "            return head\n",
    "        res = ListNode(0)\n",
    "        cur = res\n",
    "        for x, y in pairwise(arr):\n",
    "            # print(x, y)\n",
    "            cur.next = ListNode(x)\n",
    "            cur = cur.next\n",
    "            tmp = math.gcd(x, y)\n",
    "            cur.next = ListNode(tmp)\n",
    "            cur = cur.next\n",
    "            # cur.next = ListNode(y)\n",
    "            # cur = cur.next\n",
    "        cur.next = ListNode(arr[-1])\n",
    "        return res.next\n",
    "            \n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "        l = []\n",
    "        p = head\n",
    "        while p:\n",
    "            l.append(p.val)\n",
    "            p = p.next\n",
    "        r = []\n",
    "        for i in range(len(l)):\n",
    "            if i == 0:\n",
    "                r.append(l[i])\n",
    "            else:\n",
    "                r.append(math.gcd(l[i], l[i - 1]))\n",
    "                r.append(l[i])\n",
    "        h = ListNode()\n",
    "        p = h\n",
    "        for k in r:\n",
    "            p.next = ListNode(k)\n",
    "            p = p.next\n",
    "        return h.next"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for singly-linked list.\n",
    "# class ListNode:\n",
    "#     def __init__(self, val=0, next=None):\n",
    "#         self.val = val\n",
    "#         self.next = next\n",
    "class Solution:\n",
    "    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:\n",
    "\n",
    "        h = head\n",
    "        ans = []\n",
    "        while h!=None:\n",
    "            ans.append(h.val)\n",
    "            h = h.next\n",
    "\n",
    "        ret = []\n",
    "        for i in range(len(ans)-1):\n",
    "            a = ans[i]\n",
    "            b = ans[i+1]\n",
    "            \n",
    "            while b != 0:\n",
    "                a, b = b, a % b\n",
    "            ret.append(ans[i])\n",
    "            ret.append(a)\n",
    "        ret.append(ans[-1])\n",
    "\n",
    "        root = ListNode(ret[0])\n",
    "        current = root\n",
    "\n",
    "        # 创建剩余节点\n",
    "        for i in range(1, len(ret)):\n",
    "            current.next = ListNode(ret[i])\n",
    "            current = current.next\n",
    "        \n",
    "        return root\n",
    "\n",
    "            \n",
    "            \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        \n",
    "        ans = []\n",
    "        l = len(intervals)\n",
    "\n",
    "        for i in range(l):\n",
    "            if intervals[i][1] < newInterval[0]:\n",
    "                ans.append(intervals[i])\n",
    "            elif intervals[i][0] > newInterval[1]:\n",
    "                ans.append(newInterval)\n",
    "                if i == l - 1:\n",
    "                    ans.append(intervals[i])\n",
    "                else:\n",
    "                    ans.extend(intervals[i:])             \n",
    "                return ans\n",
    "            else:\n",
    "                newInterval[0] = min(intervals[i][0], newInterval[0])\n",
    "                newInterval[1] = max(intervals[i][1], newInterval[1])\n",
    "        \n",
    "        ans.append(newInterval)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for an interval.\n",
    "# class Interval:\n",
    "#     def __init__(self, s=0, e=0):\n",
    "#         self.start = s\n",
    "#         self.end = e\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals, newInterval):\n",
    "        \"\"\"\n",
    "        :type intervals: List[Interval]\n",
    "        :type newInterval: Interval\n",
    "        :rtype: List[Interval]\n",
    "        \"\"\"\n",
    "        ans, flag = [], 1\n",
    "        for item in intervals:\n",
    "            temp = Interval(max(newInterval.start, item.start), min(newInterval.end, item.end))\n",
    "            if temp.end >= temp.start:\n",
    "                flag = 0\n",
    "                new = Interval(min(newInterval.start, item.start), max(newInterval.end, item.end))\n",
    "                if ans and ans[-1].end >= new.start:\n",
    "                    ans[-1].end = new.end\n",
    "                else:\n",
    "                    ans.append(new)\n",
    "            else:\n",
    "                if flag and item.start > newInterval.end:\n",
    "                    ans.append(newInterval)\n",
    "                    flag = 0\n",
    "                if ans and ans[-1].end >= item.start:\n",
    "                    ans[-1].end = item.end\n",
    "                else:\n",
    "                    ans.append(item)\n",
    "        if not ans or ans[-1].end < newInterval.start:\n",
    "            ans.append(newInterval)\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for an interval.\n",
    "# class Interval:\n",
    "#     def __init__(self, s=0, e=0):\n",
    "#         self.start = s\n",
    "#         self.end = e\n",
    "\n",
    "class Solution:\n",
    "    \"\"\"\n",
    "    :type intervals: List[Interval]\n",
    "    :type newInterval: Interval\n",
    "    :rtype: List[Interval]\n",
    "    \"\"\"\n",
    "    def insert(self, intervals, newInterval):\n",
    "        newLeft = newInterval.start\n",
    "        newRight = newInterval.end\n",
    "        keepLast = False\n",
    "        start = -1\n",
    "        end = -1\n",
    "        for [i, interval] in enumerate(intervals):\n",
    "            left = interval.start\n",
    "            right = interval.end\n",
    "            if newLeft <= left and start == -1:\n",
    "                start = i\n",
    "                nextLeft = newLeft\n",
    "            if newLeft > left and newLeft <= right:\n",
    "                start = i\n",
    "                nextLeft = left\n",
    "            if newRight < left:\n",
    "                end = i\n",
    "                keepLast = True\n",
    "                nextRight = newRight\n",
    "                break\n",
    "            if newRight >= left and newRight <= right:\n",
    "                end = i\n",
    "                nextRight = right\n",
    "                break\n",
    "\n",
    "        if start == -1:\n",
    "            start = len(intervals)\n",
    "            nextLeft = newLeft\n",
    "        if end == -1:\n",
    "            end = len(intervals)\n",
    "            nextRight = newRight\n",
    "\n",
    "        realEnd = end if keepLast else end + 1\n",
    "        nextInterval = Interval(nextLeft, nextRight)\n",
    "        return intervals[:start] + [nextInterval] + intervals[realEnd:]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for an interval.\n",
    "# class Interval:\n",
    "#     def __init__(self, s=0, e=0):\n",
    "#         self.start = s\n",
    "#         self.end = e\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals, newInterval):\n",
    "        \"\"\"\n",
    "        :type intervals: List[Interval]\n",
    "        :type newInterval: Interval\n",
    "        :rtype: List[Interval]\n",
    "        \"\"\"\n",
    "        if not intervals:\n",
    "            return [newInterval]\n",
    "        ans = []\n",
    "        for i in range(len(intervals)):\n",
    "            if newInterval.start > intervals[i].end:\n",
    "                ans.append(intervals[i])\n",
    "            elif newInterval.end < intervals[i].start:\n",
    "                ans.append(newInterval)\n",
    "                ans += intervals[i:]\n",
    "                break\n",
    "            else:\n",
    "                newInterval.start = min(newInterval.start, intervals[i].start)\n",
    "                newInterval.end = max(newInterval.end, intervals[i].end)\n",
    "        if not ans or ans[-1].end < newInterval.start:\n",
    "            ans.append(newInterval)\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for an interval.\n",
    "# class Interval:\n",
    "#     def __init__(self, s=0, e=0):\n",
    "#         self.start = s\n",
    "#         self.end = e\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[Interval], newInterval: Interval) -> List[Interval]:\n",
    "        intervals.append(newInterval)\n",
    "        intervals = sorted(intervals,key = lambda l:l.start)\n",
    "        resultl = []\n",
    "        if len(intervals)<=1:\n",
    "            return intervals\n",
    "        for i in range(1,len(intervals)):\n",
    "            last = intervals[i-1]\n",
    "            now = intervals[i]\n",
    "            if now.start <= last.end:\n",
    "               now.start = last.start\n",
    "               now.end = max(now.end,last.end)\n",
    "            else:\n",
    "                resultl.append(intervals[i-1])\n",
    "        \n",
    "        resultl.append(intervals[i])\n",
    "        return resultl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for an interval.\n",
    "# class Interval:\n",
    "#     def __init__(self, s=0, e=0):\n",
    "#         self.start = s\n",
    "#         self.end = e\n",
    "from operator import itemgetter\n",
    "class Solution:\n",
    "    def insert(self, _intervals, newInterval):\n",
    "        \"\"\"\n",
    "        :type intervals: List[Interval]\n",
    "        :type newInterval: Interval\n",
    "        :rtype: List[Interval]\n",
    "        \"\"\"\n",
    "        intervals = [[x.start,x.end] for x in _intervals]\n",
    "        newinterval = [newInterval.start,newInterval.end]\n",
    "        intervals.append(newinterval)\n",
    "        if intervals == []:\n",
    "            return []\n",
    "        while True:\n",
    "            intervals.sort(key=itemgetter(0,1))\n",
    "            count = 0\n",
    "            for i in range(len(intervals)-1):\n",
    "                if intervals[i+1][0] <= intervals[i][1] <=intervals[i+1][1] or intervals[i][0] <=intervals[i+1][1] <= intervals[i][1]:\n",
    "                    intervals[i][0] = min(intervals[i][0],intervals[i+1][0])\n",
    "                    intervals[i][1] = max(intervals[i][1],intervals[i+1][1])\n",
    "                    intervals[i+1][0] = min(intervals[i][0], intervals[i + 1][0])\n",
    "                    intervals[i+1][1] = max(intervals[i][1], intervals[i + 1][1])\n",
    "                else:\n",
    "                    count+=1\n",
    "                    continue\n",
    "            if count == len(intervals)-1:\n",
    "                break\n",
    "            temp_l = list(set([str(i) for i in intervals]))\n",
    "            intervals = [eval((i)) for i in temp_l]\n",
    "        return intervals"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for an interval.\n",
    "# class Interval:\n",
    "#     def __init__(self, s=0, e=0):\n",
    "#         self.start = s\n",
    "#         self.end = e\n",
    "\n",
    "class Solution:\n",
    "    def merge(self, intervals):\n",
    "        res_list = []\n",
    "        length = len(intervals)\n",
    "        if length <= 1:\n",
    "            return intervals\n",
    "        base_start, base_end = intervals[0].start, intervals[0].end\n",
    "        for i in range(1, length):\n",
    "            if intervals[i].start <= base_end:\n",
    "                base_end = max(intervals[i].end, base_end)\n",
    "            else:\n",
    "                res_list.append([base_start, base_end])\n",
    "                base_start, base_end = intervals[i].start, intervals[i].end\n",
    "        res_list.append([base_start, base_end])\n",
    "        return res_list\n",
    "    def insert(self, intervals, newInterval):\n",
    "        \"\"\"\n",
    "        :type intervals: List[Interval]\n",
    "        :type newInterval: Interval\n",
    "        :rtype: List[Interval]\n",
    "        \"\"\"\n",
    "        length = len(intervals)\n",
    "        if length == 0:\n",
    "            intervals.insert(0, newInterval)\n",
    "        for i in range(length):\n",
    "            if newInterval.start <= intervals[i].start:\n",
    "                intervals.insert(i, newInterval)\n",
    "                break\n",
    "            if i == length - 1:\n",
    "                intervals.append(newInterval)\n",
    "        print(intervals)\n",
    "        return self.merge(intervals)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for an interval.\n",
    "# class Interval:\n",
    "#     def __init__(self, s=0, e=0):\n",
    "#         self.start = s\n",
    "#         self.end = e\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals, newInterval):\n",
    "        \"\"\"\n",
    "        :type intervals: List[Interval]\n",
    "        :type newInterval: Interval\n",
    "        :rtype: List[Interval]\n",
    "        \"\"\"\n",
    "        result = []\n",
    "        sort_arr = []\n",
    "        inter_num = len(intervals)\n",
    "        for i in range(inter_num):\n",
    "            sort_arr.append([intervals[i].start,[i]])\n",
    "            sort_arr.append([intervals[i].end,[i]])\n",
    "        \n",
    "        \n",
    "        l = 0\n",
    "        r = len(sort_arr)-1\n",
    "        while r>l:\n",
    "            mid = (l+r)//2\n",
    "            if sort_arr[mid][0] < newInterval.start:\n",
    "                l = mid + 1\n",
    "            else:\n",
    "                r = mid   \n",
    "        if len(sort_arr)==0 or sort_arr[l][0] < newInterval.start:\n",
    "            sort_arr.insert(l+1,[newInterval.start,[inter_num]])\n",
    "        elif sort_arr[l][0] == newInterval.start:\n",
    "            sort_arr[l][1].append(inter_num)\n",
    "        else:\n",
    "            sort_arr.insert(l,[newInterval.start,[inter_num]])\n",
    "            \n",
    "        l = 0\n",
    "        r = len(sort_arr)-1\n",
    "        while r>l:\n",
    "            mid = (l+r)//2\n",
    "            if sort_arr[mid][0] < newInterval.end:\n",
    "                l = mid + 1\n",
    "            else:\n",
    "                r = mid   \n",
    "        if len(sort_arr)==0 or sort_arr[l][0] < newInterval.end:\n",
    "            sort_arr.insert(l+1,[newInterval.end,[inter_num]])\n",
    "        elif sort_arr[l][0] == newInterval.end:\n",
    "            sort_arr[l][1].append(inter_num)\n",
    "        else:\n",
    "            sort_arr.insert(l,[newInterval.end,[inter_num]])\n",
    "                \n",
    "        temp_dict = {}\n",
    "        temp_arr = []\n",
    "        for x,arr in sort_arr:\n",
    "            temp_arr.append(x)\n",
    "            for y in arr:\n",
    "                if y not in temp_dict:\n",
    "                    temp_dict[y] = 1\n",
    "                else:\n",
    "                    temp_dict[y] += 1\n",
    "            \n",
    "            ok = True\n",
    "            for key in temp_dict:\n",
    "                if temp_dict[key] == 1:\n",
    "                    ok = False\n",
    "                    break\n",
    "            if ok:\n",
    "                result.append(Interval(temp_arr[0],temp_arr[-1]))\n",
    "                temp_dict = {}\n",
    "                temp_arr = []\n",
    "                \n",
    "        return result\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        if len(intervals) == 0:\n",
    "            return [newInterval]\n",
    "        # 新区间可能影响的元素范围 （影响范围包含start_index，end_index位置区间）\n",
    "        start_index = 0\n",
    "        end_index = len(intervals) - 1\n",
    "        for i, interval in enumerate(intervals):\n",
    "            if newInterval[0] > interval[1]:\n",
    "                # 新区间最小值定落在 start_index 位置区间元素右边界的右侧（未影响到 start_index 区间）\n",
    "                # 随着遍历进行，start_index 最终更新为新区间左侧的最后一个不收影响的区间位置\n",
    "                start_index = i\n",
    "            if newInterval[1] < interval[0]:\n",
    "                # 新区间最大值定落在 end_index 位置区间元素左边界的左侧（未影响到 end_index 区间）\n",
    "                # 找到新区间右侧第一个不受影响的位置即可结束循环\n",
    "                end_index = i\n",
    "                break\n",
    "        if newInterval[0] > intervals[start_index][1]:\n",
    "            # 更新 start_index 为受影响的 区间元素\n",
    "            start_index += 1\n",
    "        if newInterval[1] < intervals[end_index][0]:\n",
    "            # 更新 end_index 为受影响的 区间元素\n",
    "            end_index -= 1\n",
    "        # 新区间与所有受影响的区间合并后的最小值\n",
    "        min_val = min(newInterval[0], intervals[start_index][0]) if start_index < len(intervals) else newInterval[0]\n",
    "        # 新区间与所有受影响的区间合并后的最大值\n",
    "        max_val = max(newInterval[1], intervals[end_index][1]) if 0 <= end_index else newInterval[1]\n",
    "        # 前部分未受影响区间 + 合并后的新区间 + 后部分未受影响的区间\n",
    "        return intervals[:start_index] + [[min_val, max_val]] + intervals[end_index + 1:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        if not intervals:\n",
    "            intervals.append(newInterval)\n",
    "            return intervals\n",
    "        output=[]\n",
    "        i=0\n",
    "        intervals.append([float(\"inf\"),0])\n",
    "        n=len(intervals)\n",
    "        while(i<n):\n",
    "            if intervals[i][0]<newInterval[0] and i<n-1:\n",
    "                output.append(intervals[i])\n",
    "                i+=1\n",
    "            else:\n",
    "                if i>0:\n",
    "                    if intervals[i-1][1]>=newInterval[0]:\n",
    "                        intervals[i-1][1]=max(intervals[i-1][1],newInterval[1])\n",
    "                    else:\n",
    "                        output.append(newInterval)\n",
    "                else:\n",
    "                    output.append(newInterval)\n",
    "                break\n",
    "        #print(output,i)\n",
    "        intervals.pop()\n",
    "        while(i<n-1):\n",
    "            if output[-1][1]>=intervals[i][0]:\n",
    "                output[-1][1]=max(output[-1][1],intervals[i][1])\n",
    "            else:\n",
    "                output.append(intervals[i])\n",
    "            i+=1\n",
    "        return output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        n = len(intervals)\n",
    "        res = []\n",
    "        i = 0\n",
    "        while i<n:\n",
    "            if newInterval[1]<intervals[i][0]:\n",
    "                res.append(newInterval)\n",
    "                return res + intervals[i:]\n",
    "            elif  newInterval[0]>intervals[i][1]:\n",
    "                res.append(intervals[i])\n",
    "                i+=1\n",
    "            else:\n",
    "                left = min(intervals[i][0],newInterval[0])\n",
    "                right = max(intervals[i][1],newInterval[1])\n",
    "                while i<n-1 and intervals[i+1][0]<=right:\n",
    "                    i+=1\n",
    "                    right = max(right,intervals[i][1])\n",
    "                res.append([left,right])\n",
    "                return res + intervals[i+1:]\n",
    "        return res+[newInterval]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        # 初始状况判断\n",
    "        if not newInterval:\n",
    "            return intervals\n",
    "        if not intervals:\n",
    "            return [newInterval]\n",
    "        # 已经是起点有序的了\n",
    "        i = 0\n",
    "        intervalsLen = len(intervals)\n",
    "        while i < intervalsLen and intervals[i][1] < newInterval[0]:\n",
    "            i += 1\n",
    "        # 保存删除之前的位置，最后在这个位置上插入\n",
    "        tempI = i\n",
    "        while i < intervalsLen and intervals[i][0] <= newInterval[1]:\n",
    "            newInterval[0] = min(newInterval[0], intervals[i][0])\n",
    "            newInterval[1] = max(newInterval[1], intervals[i][1])\n",
    "            i += 1\n",
    "        else:\n",
    "            del intervals[tempI:i]\n",
    "            intervals.insert(tempI, newInterval)\n",
    "        return intervals\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        nums = [0] * (len(intervals)*2)\n",
    "        for step, (i, j) in enumerate(intervals):\n",
    "            nums[step*2] = i\n",
    "            nums[step*2+1] = j\n",
    "        import bisect\n",
    "        li = bisect.bisect_left(nums, newInterval[0])\n",
    "        ri = bisect.bisect_right(nums, newInterval[1])\n",
    "        res1 = intervals[:li//2]\n",
    "        t = 1 if ri%2==1 else 0\n",
    "        res2 = intervals[ri//2+t:]\n",
    "        print(li,ri)\n",
    "        if li%2 == 1:\n",
    "            inter = [nums[li-1], None]\n",
    "        else:\n",
    "            inter = [newInterval[0], None]\n",
    "        if ri % 2 == 1 or (ri < len(nums) and nums[ri] == newInterval[1]):\n",
    "            inter[1] = nums[ri]\n",
    "        else:\n",
    "            inter[1] = newInterval[1]\n",
    "        return res1 + [inter] + res2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        if len(intervals) == 0:\n",
    "            return [newInterval]\n",
    "        def i2intervali(i):\n",
    "            return i//2, i%2\n",
    "        def intervali2i(i,j):\n",
    "            return i*2+j\n",
    "        def bisect(intervals, x, left=True):\n",
    "            if x > intervals[-1][1]:\n",
    "                return len(intervals), 0\n",
    "            l,h = 0, len(intervals)*2-1\n",
    "            while l < h:\n",
    "                k = (l + h) // 2\n",
    "                i,j = i2intervali(k)\n",
    "                if left:\n",
    "                    if intervals[i][j] < x:\n",
    "                        l = k+1\n",
    "                    else:\n",
    "                        h = k\n",
    "                else:\n",
    "                    if intervals[i][j] <= x:\n",
    "                        l = k+1\n",
    "                    else:\n",
    "                        h = k\n",
    "            return i2intervali(h)\n",
    "\n",
    "        li, lj = bisect(intervals, newInterval[0], left=True)\n",
    "        ri, rj = bisect(intervals, newInterval[1], left=False)\n",
    "        res1 = intervals[:li]\n",
    "        res2 = intervals[ri+rj:]\n",
    "        print(li,lj, ri,rj)\n",
    "        if lj == 1:\n",
    "            inter = [intervals[li][0], None]\n",
    "        else:\n",
    "            inter = [newInterval[0], None]\n",
    "        if rj == 1 :\n",
    "            inter[1] = intervals[ri][1]\n",
    "        else:\n",
    "            inter[1] = newInterval[1]\n",
    "        return res1 + [inter] + res2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        if len(intervals)==0:\n",
    "            return [newInterval]\n",
    "        def binarysearch(l,i,left,right):\n",
    "            if left>right:\n",
    "                return right\n",
    "            mid=left+((right-left)>>1)\n",
    "            if intervals[mid][0]<=i<=intervals[mid][1]:\n",
    "                return mid\n",
    "            elif l[mid][1]<i:\n",
    "                return binarysearch(l,i,mid+1,right)\n",
    "            else:\n",
    "                return binarysearch(l,i,left,mid-1)\n",
    "        index1=binarysearch(intervals,newInterval[0],0,len(intervals)-1)\n",
    "        index2=binarysearch(intervals,newInterval[1],0,len(intervals)-1)\n",
    "        print(index1,index2)\n",
    "        if index1==index2:\n",
    "            if index1==-1:\n",
    "                intervals.insert(0,newInterval)\n",
    "                return intervals\n",
    "            if intervals[index1][1]>=newInterval[0]:\n",
    "                if intervals[index1][1]<newInterval[1]:\n",
    "                    intervals[index1]=[intervals[index1][0],newInterval[1]]\n",
    "            else:\n",
    "                intervals.insert(index1+1,newInterval)\n",
    "            return intervals\n",
    "        else:\n",
    "            if index1==-1:\n",
    "                index1+=1\n",
    "                intervals[index1]=[newInterval[0],max(intervals[index2][1],newInterval[1])]\n",
    "                index1+=1\n",
    "                index2+=1\n",
    "                while index2<len(intervals):\n",
    "                    intervals[index1]=intervals[index2]\n",
    "                    index1+=1\n",
    "                    index2+=1\n",
    "                return intervals[:index1]\n",
    "            elif intervals[index1][1]<newInterval[0]:\n",
    "                index1+=1\n",
    "                intervals[index1]=[newInterval[0],max(intervals[index2][1],newInterval[1])]\n",
    "                index1+=1\n",
    "                index2+=1\n",
    "                while index2<len(intervals):\n",
    "                    intervals[index1]=intervals[index2]\n",
    "                    index1+=1\n",
    "                    index2+=1\n",
    "                return intervals[:index1]\n",
    "            else:\n",
    "                intervals[index1]=[intervals[index1][0],max(intervals[index2][1],newInterval[1])]\n",
    "                index2+=1\n",
    "                index1+=1\n",
    "                while index2<len(intervals):\n",
    "                    intervals[index1]=intervals[index2]\n",
    "                    index1+=1\n",
    "                    index2+=1\n",
    "                return intervals[:index1]\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        intervals.append(newInterval)\n",
    "        intervals.sort(key=lambda a:(a[0],a[1]))\n",
    "        \n",
    "        res = [intervals[0]]\n",
    "        for i in intervals:\n",
    "            if res[-1][1] >= i[0]:\n",
    "                res[-1][1] = max(res[-1][1],i[1])\n",
    "            else:\n",
    "                res.append(i)\n",
    "        return res\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        j,k=-1,-1\n",
    "        m,n=-1,-1\n",
    "        def _in(p,l):\n",
    "            return p>=l[0] and p<=l[1]\n",
    "        for i in range(len(intervals)):\n",
    "            if _in(newInterval[0], intervals[i]):\n",
    "                j=i\n",
    "            if _in(newInterval[1], intervals[i]):\n",
    "                k=i\n",
    "        if not intervals:\n",
    "            return [newInterval]\n",
    "        \n",
    "        outintervals = [[-99999,intervals[0][0]]]\n",
    "        for ii in range(len(intervals)-1):\n",
    "            outintervals.append([intervals[ii][1], intervals[ii+1][0]])\n",
    "        outintervals.append([intervals[-1][1],999999])\n",
    "\n",
    "        for i in range(len(outintervals)):\n",
    "            if _in(newInterval[0], outintervals[i]) and j==-1:\n",
    "                m=i \n",
    "            if _in(newInterval[1], outintervals[i]) and k==-1:\n",
    "                n=i \n",
    "            \n",
    "        if j == -1 and k == -1:\n",
    "            intervals[m:n] = [[newInterval[0],newInterval[1]]]\n",
    "            pass\n",
    "        elif m == -1 and k == -1:\n",
    "            intervals[j:n] = [[intervals[j][0],newInterval[1]]]\n",
    "            pass\n",
    "        elif m == -1 and n == -1:\n",
    "            intervals[j:k+1] = [[intervals[j][0],intervals[k][1]]]\n",
    "            pass\n",
    "        elif j == -1 and n == -1:\n",
    "            intervals[m:k+1] = [[newInterval[0],intervals[k][1]]]\n",
    "            pass\n",
    "\n",
    "        return intervals"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def merge(self, intervals: List[List[int]]) -> List[List[int]]:\n",
    "        if len(intervals) <= 1:\n",
    "            return intervals\n",
    "        intervals.sort()\n",
    "        res = [intervals[0]]\n",
    "        for current in intervals:\n",
    "            if res[-1][1] >= current[0]:\n",
    "                res[-1][1] = max(res[-1][1], current[1])\n",
    "            else:\n",
    "                res.append(current)\n",
    "        return res\n",
    "\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        intervals.append(newInterval)\n",
    "        return self.merge(intervals)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        merged = []\n",
    "        flag = 1\n",
    "        for i in range(len(intervals)):\n",
    "            if intervals[i][1]<newInterval[0]:\n",
    "                merged.append(intervals[i])\n",
    "            elif intervals[i][0]>newInterval[1]:\n",
    "                if(flag):\n",
    "                    merged.append(newInterval)\n",
    "                    flag=0\n",
    "                merged.append(intervals[i])\n",
    "            else:\n",
    "                newInterval[0] = min(newInterval[0],intervals[i][0])\n",
    "                newInterval[1] = max(newInterval[1],intervals[i][1])\n",
    "        if(flag):\n",
    "            merged.append(newInterval)\n",
    "        return merged\n",
    "                \n",
    "\n",
    "\n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        left=newInterval[0]\n",
    "        right = newInterval[1]\n",
    "        flag=True\n",
    "        res=[]\n",
    "        for i in range(len(intervals)):\n",
    "            if intervals[i][0]>right:\n",
    "                if flag:\n",
    "                    res.append([left,right])\n",
    "                    flag=False\n",
    "                res.append(intervals[i])\n",
    "            elif intervals[i][1]<left:\n",
    "                res.append(intervals[i])\n",
    "            else:\n",
    "                left=min(left,intervals[i][0])\n",
    "                right=max(right,intervals[i][1])\n",
    "        if flag:\n",
    "            res.append([left,right])\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        ans = []\n",
    "        placed = False\n",
    "        mergeL, mergeR = newInterval\n",
    "        for l, r in intervals:\n",
    "            if r < mergeL:\n",
    "                ans.append((l, r))\n",
    "            elif l > mergeR:\n",
    "                if not placed:\n",
    "                    ans.append((mergeL, mergeR))\n",
    "                    placed = True\n",
    "                ans.append((l, r))\n",
    "            else:\n",
    "                mergeL, mergeR = min(mergeL, l), max(mergeR, r)\n",
    "        return ans if placed else ans + [(mergeL, mergeR)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        intervals.append(newInterval)\n",
    "        intervals.sort(key = lambda x:x[0])\n",
    "        merged = []\n",
    "        for interval in intervals:\n",
    "            if not merged or merged[-1][1] < interval[0]:\n",
    "                merged.append(interval)\n",
    "            else:\n",
    "                merged[-1][1] = max(merged[-1][1], interval[1])\n",
    "        return merged"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        a = intervals\n",
    "        bl, br = newInterval\n",
    "        ans = []\n",
    "        flag = True\n",
    "        for l, r in intervals:\n",
    "            if r < bl:\n",
    "                ans.append([l, r])\n",
    "            elif l > br:\n",
    "                if flag:\n",
    "                    ans.append([bl, br])\n",
    "                    ans.append([l, r])\n",
    "                else:\n",
    "                    ans.append([l, r])\n",
    "                flag = False\n",
    "            else:\n",
    "                bl = min(l, bl)\n",
    "                br = max(r, br)\n",
    "        if flag:\n",
    "            ans.append([bl, br])\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        ans = []\n",
    "        idx = []\n",
    "        for _, i in enumerate(intervals):\n",
    "            if min(i[1], newInterval[1]) >= max(i[0], newInterval[0]):\n",
    "                newInterval = [min(i[0], newInterval[0]), max(i[1], newInterval[1])]\n",
    "                idx.append(_)\n",
    "        if len(idx) == 0:\n",
    "            ans = intervals + [newInterval]\n",
    "            ans.sort(key= lambda x:x[0])\n",
    "        else:\n",
    "            ans = intervals[:idx[0]] + [newInterval] + intervals[idx[-1] + 1:]\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        ans = []\n",
    "        Flag = 0\n",
    "        left, right = newInterval\n",
    "        idx = -1\n",
    "        for idx,(lefti, righti) in enumerate(intervals):\n",
    "            if right < lefti:# 在当前区间的左侧\n",
    "                Flag = 1\n",
    "                ans.append([left,right])\n",
    "                break  # 也肯定在后续区间的左侧，不用再迭代了\n",
    "            elif left > righti:\n",
    "                # 可能跟后续的有交集，跳过\n",
    "                ans.append([lefti,righti])\n",
    "            else:\n",
    "                # 当前区间被合并，可能还会和后续的区间有交集\n",
    "                left = min(left,lefti)\n",
    "                right = max(right,righti)\n",
    "        if Flag:\n",
    "            ans.extend(intervals[idx:])\n",
    "        if not Flag:\n",
    "            ans.append([left,right])\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals, newInterval):\n",
    "        n = len(intervals)\n",
    "        if n == 0:\n",
    "            return [newInterval]\n",
    "        result = []\n",
    "        for i in range(n):\n",
    "            now = intervals[i]\n",
    "            if now[1] < newInterval[0]:\n",
    "                result.append(now)\n",
    "            elif now[0] <= newInterval[0] and newInterval[1] <= now[1]:\n",
    "                return intervals\n",
    "            elif now[0] <= newInterval[0] and now[1] < newInterval[1]:\n",
    "                newInterval[0] = now[0]\n",
    "            elif newInterval[0] < now[0] and now[0] <= newInterval[1] < now[1]:\n",
    "                newInterval[1] = now[1]\n",
    "            elif newInterval[1] < now[0]:\n",
    "                result.append(newInterval)\n",
    "                for j in range(i, n):\n",
    "                    result.append(intervals[j])\n",
    "                return result\n",
    "        if newInterval not in result:\n",
    "            result.append(newInterval)\n",
    "        return result\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        x, y = newInterval\n",
    "        res = []\n",
    "        done = False\n",
    "        for a, b in intervals:\n",
    "            if done or b < x:\n",
    "                res.append((a, b))\n",
    "            elif y < a:\n",
    "                res.append((x, y))\n",
    "                res.append((a, b))\n",
    "                done = True\n",
    "            else:\n",
    "                x = min(x, a)\n",
    "                y = max(y, b)\n",
    "        if not done:\n",
    "            res.append((x, y))\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:\n",
    "        \n",
    "        res= []\n",
    "        i = 0\n",
    "        # 添加所有不与新区间重叠且在新区间之前的区间\n",
    "        while i < len(intervals) and intervals[i][1] < newInterval[0]:\n",
    "            res.append(intervals[i])\n",
    "            i+= 1\n",
    "        \n",
    "         # 合并所有与新区间重叠的区间\n",
    "        while i < len(intervals) and newInterval[1] >= intervals[i][0]:\n",
    "            newInterval[0] = min(newInterval[0], intervals[i][0])\n",
    "            newInterval[1] = max(newInterval[1], intervals[i][1])\n",
    "            i += 1\n",
    "        res.append(newInterval)\n",
    "\n",
    "        # 添加剩余的区间\n",
    "        while i< len(intervals) and newInterval[1] < intervals[i][0]:\n",
    "            res.append(intervals[i])\n",
    "            i += 1\n",
    "\n",
    "        print(res)\n",
    "        return res\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def helper(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        if root==None:\n",
    "            return TreeNode(val)\n",
    "        if root.val < val:\n",
    "            root.right = self.helper(root.right, val)\n",
    "        else:\n",
    "            root.left = self.helper(root.left, val)\n",
    "        return root\n",
    "        \n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        return self.helper(root, val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root, val):\n",
    "        \"\"\"\n",
    "        :type root: TreeNode\n",
    "        :type val: int\n",
    "        :rtype: TreeNode\n",
    "        \"\"\"\n",
    "#       if root == None :\n",
    "        if not root:\n",
    "            return TreeNode(val)\n",
    "        if val > root.val:\n",
    "            root.right = self.insertIntoBST(root.right, val)\n",
    "        if val < root.val:\n",
    "            root.left = self.insertIntoBST(root.left, val)\n",
    "        return root\n",
    "#--------------------- \n",
    "\n",
    "\n",
    "\n",
    "        \n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root, val):\n",
    "        \"\"\"\n",
    "        :type root: TreeNode\n",
    "        :type val: int\n",
    "        :rtype: TreeNode\n",
    "        \"\"\"\n",
    "        res = root\n",
    "        temp = 0\n",
    "        if root == None:\n",
    "            res.val = val \n",
    "            return res\n",
    "        while root:\n",
    "            print(root)\n",
    "            if root.val > val:\n",
    "                temp = root\n",
    "                root = root.left\n",
    "            elif root.val < val:\n",
    "                temp = root\n",
    "                root = root.right\n",
    "        if temp.val > val:\n",
    "            temp.left = TreeNode(val)\n",
    "        else:\n",
    "            temp.right = TreeNode(val)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: 'TreeNode', val: 'int') -> 'TreeNode':\n",
    "        \n",
    "        \n",
    "        if root.val<val:\n",
    "            if root.right:\n",
    "                self.insertIntoBST(root.right,val)\n",
    "            else:\n",
    "                root.right=TreeNode(val)\n",
    "        if root.val>val:\n",
    "            if root.left:\n",
    "                self.insertIntoBST(root.left,val)\n",
    "            else:\n",
    "                root.left=TreeNode(val)\n",
    "        return root\n",
    "            \n",
    "                \n",
    "                \n",
    "            \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root, val):\n",
    "        \"\"\"\n",
    "        :type root: TreeNode\n",
    "        :type val: int\n",
    "        :rtype: TreeNode\n",
    "        \"\"\"\n",
    "        if root:\n",
    "            if val < root.val:\n",
    "                root.left = self.insertIntoBST(root.left, val)\n",
    "            else:\n",
    "                root.right = self.insertIntoBST(root.right, val)\n",
    "            return root\n",
    "        return TreeNode(val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root, val):\n",
    "        \"\"\"\n",
    "        :type root: TreeNode\n",
    "        :type val: int\n",
    "        :rtype: TreeNode\n",
    "        \"\"\"\n",
    "        if root == None:\n",
    "            return TreeNode(val)\n",
    "        elif root.val > val:\n",
    "            print(root.val)\n",
    "            root.left = self.insertIntoBST(root.left, val)\n",
    "        elif root.val <= val:\n",
    "            root.right = self.insertIntoBST(root.right, val)\n",
    "        return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        \n",
    "        def dfs(node):\n",
    "            if node == None:\n",
    "                return\n",
    "\n",
    "            if node.val > val:\n",
    "                if node.left == None:\n",
    "                    node.left = TreeNode(val)\n",
    "                    return\n",
    "                dfs(node.left)\n",
    "            else:\n",
    "                if node.right == None:\n",
    "                    node.right = TreeNode(val)\n",
    "                    return\n",
    "                dfs(node.right)\n",
    "\n",
    "        dfs(root)\n",
    "        return root\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        node = root\n",
    "        if root is None:\n",
    "            return TreeNode(val)\n",
    "        while True:\n",
    "            if val < node.val:\n",
    "                if node.left is None:\n",
    "                    node.left = TreeNode(val)\n",
    "                    return root\n",
    "                else:\n",
    "                    node = node.left\n",
    "            else:\n",
    "                if node.right is None:\n",
    "                    node.right = TreeNode(val)\n",
    "                    return root\n",
    "                else:\n",
    "                    node = node.right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, x):\n",
    "#         self.val = x\n",
    "#         self.left = None\n",
    "#         self.right = None\n",
    "\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        \"\"\"\n",
    "        注意: 插入的节点一定是叶子节点\n",
    "        \"\"\"\n",
    "        if root is None:\n",
    "            # 如果根节点为空 直接让root指向新创建的节点\n",
    "            root = TreeNode(val)\n",
    "            return root\n",
    "        \n",
    "        curr = root\n",
    "        parent = curr\n",
    "        # 寻找val的父节点\n",
    "        while curr is not None:\n",
    "            # 记录比较结果 下面要用到\n",
    "            cmp = val - curr.val\n",
    "            parent = curr\n",
    "            if cmp > 0:\n",
    "                # val 大于当前节点的值 往curr的右子节点找\n",
    "                curr = curr.right\n",
    "            elif cmp < 0:\n",
    "                # val小于当前节点的值 往curr的右子节点找\n",
    "                curr = curr.left\n",
    "            else:\n",
    "                # 如果相等 直接覆盖 当然也可以不做任何处理 可以直接返回root\n",
    "                curr.val = val\n",
    "                return root\n",
    "            \n",
    "        node = TreeNode(val)\n",
    "        # 根据cmp比较结果设置左或者右子节点\n",
    "        if cmp > 0:\n",
    "            parent.right = node\n",
    "        else:\n",
    "            parent.left = node\n",
    "            \n",
    "        return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "\n",
    "        def insert(root, val):\n",
    "            if not root:\n",
    "                root = TreeNode(val)\n",
    "                return root\n",
    "            \n",
    "            if val < root.val:\n",
    "                root.left = insert(root.left, val)\n",
    "            elif val > root.val:\n",
    "                root.right = insert(root.right, val)\n",
    "            return root\n",
    "        \n",
    "        return insert(root, val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        if root is None:\n",
    "            return TreeNode(val)\n",
    "        p, node = root, TreeNode(val) \n",
    "        while p is not None:\n",
    "            if p.val > val:\n",
    "                if p.left is not None:\n",
    "                    p = p.left\n",
    "                else:\n",
    "                    p.left = node \n",
    "                    return root\n",
    "            else:\n",
    "                if p.right is not None:\n",
    "                    p = p.right\n",
    "                else:\n",
    "                    p.right = node \n",
    "                    return root \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        # 这题咋这么简单，第一次提交node.val > val忘写.val了，第二次过\n",
    "        # 74.26% 5.04%\n",
    "        if not root:\n",
    "            return TreeNode(val)\n",
    "        \n",
    "        node = root\n",
    "\n",
    "        while node:\n",
    "            if node.val > val:\n",
    "                if not node.left:\n",
    "                    node.left = TreeNode(val)\n",
    "                    break\n",
    "                else:\n",
    "                    node = node.left\n",
    "                    continue\n",
    "            else:\n",
    "                if not node.right:\n",
    "                    node.right = TreeNode(val)\n",
    "                    break\n",
    "                else:\n",
    "                    node = node.right\n",
    "                    continue\n",
    "\n",
    "        return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        if not root:\n",
    "            return TreeNode(val)\n",
    "        node = root\n",
    "        while node:\n",
    "            if val < node.val:\n",
    "                if not node.left:\n",
    "                    node.left = TreeNode(val)\n",
    "                    break\n",
    "                else:\n",
    "                    node = node.left\n",
    "            else:\n",
    "                if not node.right:\n",
    "                    node.right = TreeNode(val)\n",
    "                    break\n",
    "                else:\n",
    "                    node = node.right\n",
    "        return root\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:  # 递归解决\n",
    "        if root is None:  # 如果当前节点为空，则在这个地方插入指定节点\n",
    "            root = TreeNode()  # 新建一个节点\n",
    "            root.val = val  # 节点赋值\n",
    "            return root  # 返回新建的节点\n",
    "        elif val < root.val:  # 如果插入的值小于当前节点的值\n",
    "            root.left = self.insertIntoBST(root.left, val)  # 则在当前节点的左子树中插入\n",
    "        else:\n",
    "            root.right = self.insertIntoBST(root.right, val)  # 否则在当前节点的右子树中中插入\n",
    "        return root  # 返回\n",
    "\n",
    "\n",
    "# class Solution:\n",
    "#     def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:  # 非递归解决\n",
    "#         if root is None:  # 如果当前节点为空，则在这个地方插入指定节点\n",
    "#             root = TreeNode(val=val)  # 新建一个节点\n",
    "#             return root  # 返回新建的节点\n",
    "#         node = root  # 记根节点为当前节点\n",
    "#         while node:  # 如果当前节点不为空\n",
    "#             pre = node  # 记录当前节点，用于后续的连接操作\n",
    "#             if val < node.val:  # 如果插入的值小于当前节点的值\n",
    "#                 node = node.left  # 当前节点向左子树转移\n",
    "#             elif val > node.val: \n",
    "#                 node = node.right  # 否则当前节点向右子树转移\n",
    "#         new_node = TreeNode(val=val)  # 循环结束，说明已经到了底部，新建节点并赋值\n",
    "#         if val < pre.val:  # 根据插入的值与父节点值的大小，决定插入到父节点的左右子树上\n",
    "#             pre.left = new_node\n",
    "#         else:\n",
    "#             pre.right = new_node\n",
    "#         return root  # 返回根节点"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        if root is None:\n",
    "            return TreeNode(val)\n",
    "        if root.val > val:\n",
    "            root.left = self.insertIntoBST(root.left, val)\n",
    "        else:\n",
    "            root.right = self.insertIntoBST(root.right, val)\n",
    "        return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "        if not root:\n",
    "            return TreeNode(val)\n",
    "        root1=TreeNode(root.val)\n",
    "        def port(node,node1):\n",
    "            if node.left!=None:\n",
    "                node1.left=TreeNode(node.left.val)\n",
    "                port(node.left,node1.left)\n",
    "            if node.right!=None:\n",
    "                node1.right=TreeNode(node.right.val)\n",
    "                port(node.right,node1.right)             \n",
    "        port(root,root1)\n",
    "        def f(node):\n",
    "            if node.val>val:\n",
    "                if node.left:\n",
    "                    f(node.left)\n",
    "                else:\n",
    "                    node.left=TreeNode(val)\n",
    "                    return\n",
    "            elif node.val<val:\n",
    "                if node.right:\n",
    "                    f(node.right)\n",
    "                else:\n",
    "                    node.right=TreeNode(val)\n",
    "                    return\n",
    "        f(root1)\n",
    "        return root1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:\n",
    "        if not root:\n",
    "            return TreeNode(val)\n",
    "        if root.val < val:\n",
    "            root.right = self.insertIntoBST(root.right, val)\n",
    "        elif root.val > val:\n",
    "            root.left = self.insertIntoBST(root.left, val)\n",
    "        return root\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:\n",
    "        if not root:\n",
    "            return TreeNode(val)\n",
    "        \n",
    "        pos = root\n",
    "        while pos:\n",
    "            if val < pos.val:\n",
    "                if not pos.left:\n",
    "                    pos.left = TreeNode(val)\n",
    "                    break\n",
    "                else:\n",
    "                    pos = pos.left\n",
    "            else:\n",
    "                if not pos.right:\n",
    "                    pos.right = TreeNode(val)\n",
    "                    break\n",
    "                else:\n",
    "                    pos = pos.right\n",
    "        \n",
    "        return root\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:\n",
    "        if not root:\n",
    "            return TreeNode(val=val)\n",
    "        point=root\n",
    "        while True:\n",
    "            if val<point.val:\n",
    "                if point.left:\n",
    "                    point=point.left\n",
    "                else:\n",
    "                    point.left=TreeNode(val=val)\n",
    "                    return root\n",
    "            elif val>point.val:\n",
    "                if point.right:\n",
    "                    point=point.right\n",
    "                else:\n",
    "                    point.right=TreeNode(val=val)\n",
    "                    return root\n",
    "        return root\n",
    "                \n",
    "       \n",
    "        \n",
    "            \n",
    "      \n",
    "      \n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:\n",
    "        def findplace(root: TreeNode, val: int):\n",
    "            if not root:\n",
    "                root = TreeNode()\n",
    "                root.val = val\n",
    "                return root\n",
    "            if root.val > val and root.left:\n",
    "                findplace(root.left, val)\n",
    "            if root.val > val and not root.left:\n",
    "                root.left = findplace(root.left, val)\n",
    "            if root.val < val and root.right:\n",
    "                findplace(root.right, val)\n",
    "            if root.val < val and not root.right:\n",
    "                root.right = findplace(root.right, val)\n",
    "        if root:\n",
    "            findplace(root, val)\n",
    "        else:\n",
    "            root = TreeNode()\n",
    "            root.val = val\n",
    "        return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:\n",
    "\n",
    "        def dfs(root, val):\n",
    "            print(root)\n",
    "            if root.left and root.left.val < val < root.val:\n",
    "                if root.left.right:\n",
    "                    dfs(root.left, val)\n",
    "                else:\n",
    "                    tmp = root.left\n",
    "                    root.left = TreeNode(val)\n",
    "                    root.left.left = tmp\n",
    "                return\n",
    "            elif not root.left and val < root.val:\n",
    "                root.left = TreeNode(val)\n",
    "                return\n",
    "            elif val < root.val:\n",
    "                dfs(root.left, val)\n",
    "            elif root.right and root.val < val < root.right.val:\n",
    "                if root.right.left:\n",
    "                    dfs(root.right, val)\n",
    "                else:\n",
    "                    tmp = root.right\n",
    "                    root.right = TreeNode(val)\n",
    "                    root.right.right = tmp\n",
    "                return\n",
    "            elif not root.right and val > root.val:\n",
    "                root.right = TreeNode(val)\n",
    "                return\n",
    "            else:\n",
    "                dfs(root.right, val)\n",
    "            \n",
    "\n",
    "        if not root:\n",
    "            return TreeNode(val)\n",
    "        dfs(root, val)\n",
    "        return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:\n",
    "            new = TreeNode(val)\n",
    "            if not root: #遇到空节点，返回一个新的节点\n",
    "                return new\n",
    "            elif not root.left and root.val > val: #否则若没有左孩子 并且val 小于 rootroot，插入到左孩子\n",
    "                root.left = new\n",
    "            elif not root.right and root.val<val: #同上\n",
    "                root.right = new\n",
    "\n",
    "            if val>root.val:\n",
    "                self.insertIntoBST(root.right, val)\n",
    "            if val < root.val :\n",
    "                self.insertIntoBST(root.left, val)\n",
    "            print(root)\n",
    "            return root\n",
    "        \n",
    "        # return insert(cur,val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:\n",
    "        newNode = TreeNode(val)\n",
    "        if not root: return newNode\n",
    "        if not root.left and val < root.val:\n",
    "            root.left = newNode\n",
    "        if not root.right and val > root.val:\n",
    "            root.right = newNode\n",
    "        if val < root.val:\n",
    "            self.insertIntoBST(root.left, val)\n",
    "        if val > root.val:\n",
    "            self.insertIntoBST(root.right, val)\n",
    "        return root\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:\n",
    "\n",
    "        if root == None:  # 公司里没人，直接当老大，返回走人\n",
    "            return TreeNode(val)\n",
    "\n",
    "        def DangDidi(root, baba, val):\n",
    "\n",
    "            if root == None:  # 找到自己所属的爸爸了。\n",
    "                if val < baba.val:  # 小就站左边。\n",
    "                    baba.left = TreeNode(val)\n",
    "                else:  # 大就站右边。\n",
    "                    baba.right = TreeNode(val)\n",
    "                return\n",
    "\n",
    "            if val < root.val:  # 小就往左找。\n",
    "                DangDidi(root.left, root, val)\n",
    "            else:  # 大就往右找。\n",
    "                DangDidi(root.right, root, val)\n",
    "\n",
    "        DangDidi(root, None, val)\n",
    "        return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "# Definition for a binary tree node.\n",
    "# class TreeNode:\n",
    "#     def __init__(self, val=0, left=None, right=None):\n",
    "#         self.val = val\n",
    "#         self.left = left\n",
    "#         self.right = right\n",
    "class Solution:\n",
    "    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:\n",
    "        if root is None:\n",
    "            return TreeNode(val)\n",
    "        \n",
    "        if root.val > val:\n",
    "            root.left = self.insertIntoBST(root.left, val)\n",
    "        elif root.val < val:\n",
    "            root.right = self.insertIntoBST(root.right, val)\n",
    "        \n",
    "        return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "  def insert(self, head, val):\n",
    "    \"\"\"\n",
    "    :type head: Node\n",
    "    :type val: int\n",
    "    :rtype: Node\n",
    "    \"\"\"\n",
    "    newNode = Node( val, None )\n",
    "    newNode.next = newNode\n",
    "\n",
    "    if head == None:\n",
    "      return newNode\n",
    "    if head.next == head:\n",
    "      head.next, newNode.next = newNode, head\n",
    "      return head\n",
    "\n",
    "    p, n = head, head.next\n",
    "    while p.val <= n.val and not ( p.val <= val <= n.val ):\n",
    "      p = n\n",
    "      n = n.next\n",
    "      if p == head:\n",
    "        head.next, newNode.next = newNode, n\n",
    "        break\n",
    "\n",
    "    if p.val <= val or val <= n.val:\n",
    "      p.next, newNode.next = newNode, n\n",
    "      return head\n",
    "\n",
    "    p = n\n",
    "    n = n.next\n",
    "    while p != head and not ( p.val <= val <= n.val ):\n",
    "      p = n\n",
    "      n = n.next\n",
    "\n",
    "    p.next, newNode.next = newNode, n\n",
    "    return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(insertVal)\n",
    "        if not head:\n",
    "            node.next = node\n",
    "            return node\n",
    "        \n",
    "        ptr = head.next\n",
    "\n",
    "        # ptr.val <= ptr.next.val and ptr.val <= intervalVal and insertVal <= ptr.next.val\n",
    "        # ptr.val >= ptr.next.val (max -> min) and (ptr.val <= intervalVal or interval <= ptr.next.val)\n",
    "\n",
    "        while True:\n",
    "            if ptr.val <= ptr.next.val:\n",
    "                if ptr.val <= insertVal and insertVal <= ptr.next.val:\n",
    "                    break\n",
    "            else:\n",
    "                if ptr.val <= insertVal or insertVal <= ptr.next.val:\n",
    "                    break\n",
    "\n",
    "            if ptr == head:\n",
    "                break\n",
    "            else:\n",
    "                 ptr = ptr.next\n",
    "        \n",
    "        \n",
    "        node.next = ptr.next\n",
    "        ptr.next = node\n",
    "\n",
    "        return head\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        iv = Node(insertVal)\n",
    "        if not head:\n",
    "            iv.next = iv\n",
    "            return iv\n",
    "        else:\n",
    "            it = head\n",
    "            r = False\n",
    "            while True:\n",
    "                if (it.val <= iv.val <=it.next.val) or \\\n",
    "                    ((it.next.val < it.val or (it.next.val == it.val and r)) \\\n",
    "                    and (iv.val <= it.next.val or it.val <= iv.val)):\n",
    "                    iv.next = it.next\n",
    "                    it.next = iv\n",
    "                    break\n",
    "                else:\n",
    "                    it = it.next\n",
    "                if head == it.next:\n",
    "                    r = True\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "\n",
    "        if not head:\n",
    "            the_node = Node(val=insertVal)\n",
    "            the_node.next = the_node\n",
    "            return the_node\n",
    "\n",
    "        \n",
    "        prev, curr = head, head.next\n",
    "\n",
    "        while curr != head:\n",
    "            if insertVal >= prev.val and insertVal <= curr.val:\n",
    "                prev.next = Node(insertVal, curr)\n",
    "                return head\n",
    "            else:\n",
    "                prev = prev.next\n",
    "                curr = curr.next\n",
    "        \n",
    "        if insertVal >= prev.val and insertVal <= curr.val:\n",
    "            prev.next = Node(insertVal, curr)\n",
    "            return head\n",
    "\n",
    "\n",
    "        while prev.val < curr.val:\n",
    "            prev = prev.next\n",
    "            curr = curr.next\n",
    "\n",
    "        prev.next = Node(insertVal, curr)\n",
    "\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        cur=head\n",
    "        new_node=Node(insertVal)\n",
    "        if cur==None:\n",
    "            new_node.next=new_node\n",
    "            return new_node\n",
    "        if cur.next==cur:\n",
    "            cur_next=cur.next\n",
    "            cur.next=new_node\n",
    "            new_node.next=cur_next\n",
    "            return head\n",
    "        \n",
    "        while True:\n",
    "            print(cur.val)\n",
    "            # cur=cur.next\n",
    "            if cur.val==insertVal:\n",
    "                cur_next=cur.next\n",
    "                cur.next=new_node\n",
    "                new_node.next=cur_next\n",
    "                break\n",
    "            if cur.next.val>cur.val:\n",
    "                # print(cur.val,cur.next.val)\n",
    "                if insertVal>=cur.val and insertVal<=cur.next.val:\n",
    "                    cur_next=cur.next\n",
    "                    cur.next=new_node\n",
    "                    new_node.next=cur_next\n",
    "                    break\n",
    "                else:\n",
    "                    cur=cur.next\n",
    "            elif cur.next.val==cur.val:\n",
    "                # if cur.next==head:\n",
    "                if cur.next==head:\n",
    "                    if insertVal>cur.val:\n",
    "                        cur_next=cur.next\n",
    "                        cur.next=new_node\n",
    "                        new_node.next=cur_next\n",
    "                        break\n",
    "                    elif insertVal<cur.next.val:\n",
    "                        cur_next=cur.next\n",
    "                        cur.next=new_node\n",
    "                        new_node.next=cur_next\n",
    "                        break\n",
    "                    else:\n",
    "                        break\n",
    "                else:\n",
    "                    cur=cur.next\n",
    "            else:\n",
    "                if insertVal>cur.val:\n",
    "                    cur_next=cur.next\n",
    "                    cur.next=new_node\n",
    "                    new_node.next=cur_next\n",
    "                    break\n",
    "                elif insertVal<cur.next.val:\n",
    "                    cur_next=cur.next\n",
    "                    cur.next=new_node\n",
    "                    new_node.next=cur_next\n",
    "                    break\n",
    "                else:\n",
    "                    # print(cur.next.val)\n",
    "                    cur=cur.next\n",
    "                    # break\n",
    "        return head           \n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head is None:\n",
    "            newNode = Node(val=insertVal, next=None)\n",
    "            newNode.next = newNode\n",
    "            return newNode\n",
    "\n",
    "        prev, curr = head, head.next\n",
    "        toInsert = False\n",
    "\n",
    "        while True:\n",
    "            if prev.val <= insertVal <= curr.val:\n",
    "                toInsert = True\n",
    "            elif prev.val > curr.val:\n",
    "                if insertVal >= prev.val or insertVal <= curr.val:\n",
    "                    toInsert = True\n",
    "\n",
    "            if toInsert:\n",
    "                prev.next = Node(insertVal, curr)\n",
    "                return head\n",
    "\n",
    "            prev, curr = curr, curr.next\n",
    "            if prev == head:\n",
    "                break\n",
    "        \n",
    "        prev.next = Node(insertVal, curr)\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            root = Node(insertVal)\n",
    "            root.next = root\n",
    "            return root\n",
    "        \n",
    "        dummy = Node(-1)\n",
    "        dummy.next = head\n",
    "        pivot, pivot_prev = None, None\n",
    "        while True:\n",
    "            if head.next == head:\n",
    "                node = Node(insertVal)\n",
    "                head.next = node\n",
    "                node.next = head\n",
    "                break\n",
    "            if head.next.val >= insertVal and head.val <= insertVal:\n",
    "                node = Node(insertVal)\n",
    "                node.next = head.next\n",
    "                head.next = node\n",
    "                return dummy.next\n",
    "            if head.val > head.next.val:\n",
    "                pivot = head.next\n",
    "                pivot_prev = head\n",
    "            head = head.next\n",
    "            if head == dummy.next:\n",
    "                if pivot:\n",
    "                    node = Node(insertVal)\n",
    "                    pivot_prev.next = node\n",
    "                    node.next = pivot\n",
    "                else:\n",
    "                    node = Node(insertVal)\n",
    "                    node.next = head.next\n",
    "                    head.next = node\n",
    "                break\n",
    "\n",
    "        return dummy.next"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            p = Node(insertVal)\n",
    "            p.next = p\n",
    "            return p\n",
    "        \n",
    "        prev,cur = head,head.next\n",
    "        tail = None\n",
    "        while True:\n",
    "            if prev.val>cur.val:\n",
    "                tail = prev\n",
    "\n",
    "            if prev.val<=insertVal<=cur.val:\n",
    "                prev.next = Node(insertVal,cur)\n",
    "                return head\n",
    "            \n",
    "\n",
    "            prev,cur = cur,cur.next \n",
    "            if prev==head:\n",
    "                break        \n",
    "        if tail:\n",
    "            tail.next = Node(insertVal,tail.next)\n",
    "            return head\n",
    "        else:\n",
    "\n",
    "            prev.next = Node(insertVal,cur)\n",
    "            return head\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(insertVal)\n",
    "\n",
    "        if not head:\n",
    "            node.next = node\n",
    "            return node\n",
    "        if head.next == head:\n",
    "            node.next = head.next\n",
    "            head.next = node\n",
    "            return head\n",
    "        \n",
    "        curr = head\n",
    "        while curr.next != head:\n",
    "            if curr.val <= insertVal and curr.next.val >= insertVal:\n",
    "                break\n",
    "            \n",
    "            if curr.val > curr.next.val:\n",
    "                if insertVal >= curr.val or curr.next.val >= insertVal:\n",
    "                    break\n",
    "            curr = curr.next\n",
    "        node.next = curr.next\n",
    "        curr.next = node\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(insertVal)\n",
    "        if not head:\n",
    "            node.next = node\n",
    "            return node\n",
    "        \n",
    "        if head.next == head:\n",
    "            head.next = node\n",
    "            node.next = head\n",
    "            return head\n",
    "        \n",
    "        cur, nxt = head, head.next\n",
    "        while nxt != head:\n",
    "            if cur.val <= insertVal <= nxt.val:\n",
    "                break\n",
    "            if cur.val > nxt.val:\n",
    "                if insertVal > cur.val or insertVal < nxt.val:\n",
    "                    break\n",
    "            cur, nxt = cur.next, nxt.next\n",
    "        cur.next, node.next = node, nxt\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(val=insertVal)\n",
    "        if not head:\n",
    "            node.next = node\n",
    "            return node\n",
    "        \n",
    "        curr = head.next\n",
    "        \n",
    "        while curr != head:\n",
    "            \n",
    "            if curr.val <=  insertVal <= curr.next.val:\n",
    "                break\n",
    "            \n",
    "            if curr.val >  curr.next.val:\n",
    "                if insertVal >= curr.val or insertVal <=curr.next.val:\n",
    "                    break\n",
    "                \n",
    "                \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "            curr = curr.next\n",
    "\n",
    "\n",
    "        node.next = curr.next\n",
    "        curr.next = node\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            node = ListNode(insertVal)\n",
    "            node.next = node\n",
    "            return node\n",
    "        maxval = head.val\n",
    "        minval = head.val\n",
    "        p = head.next\n",
    "        while p != head:\n",
    "            maxval = max(maxval, p.val)\n",
    "            minval = min(minval, p.val)\n",
    "            p = p.next\n",
    "        print(minval, maxval)\n",
    "        if insertVal >= maxval or insertVal <= minval:\n",
    "            cur = head\n",
    "            while cur:\n",
    "                if cur.val == maxval and cur.next.val == minval:\n",
    "                    break\n",
    "                cur = cur.next\n",
    "            node = ListNode(insertVal)\n",
    "            node.next = cur.next\n",
    "            cur.next = node\n",
    "        else:\n",
    "            cur = head\n",
    "            while cur.next:\n",
    "                if cur.next.val >= insertVal and cur.val <= insertVal:\n",
    "                    break\n",
    "                else:\n",
    "                    cur = cur.next\n",
    "            # print(cur.val)\n",
    "            node = ListNode(insertVal)\n",
    "            node.next = cur.next\n",
    "            cur.next = node\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head is None:\n",
    "            n = Node(insertVal)\n",
    "            n.next = n\n",
    "            return n\n",
    "\n",
    "        cur = head\n",
    "        if head.next != head:\n",
    "            while True:\n",
    "                if (cur.val <= insertVal <= cur.next.val) or (cur.val > cur.next.val and (insertVal >= cur.val or insertVal <= cur.next.val)):\n",
    "                    break\n",
    "                cur = cur.next\n",
    "                if cur == head:\n",
    "                    break\n",
    "\n",
    "        cur.next = Node(insertVal, cur.next)\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "# class Solution:\n",
    "#     def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "#         mark_head = head\n",
    "#         curr = head\n",
    "#         pre = head\n",
    "#         while curr and insertVal < curr.val:\n",
    "#             print(f'pre {curr.val}')\n",
    "#             pre = curr\n",
    "#             curr = curr.next\n",
    "#             print(f'aft {curr.val}')\n",
    "#         new = Node(insertVal)\n",
    "#         print(curr)\n",
    "#         temp = curr.next\n",
    "#         curr.next = new\n",
    "#         new.next = temp\n",
    "        \n",
    "#         return mark_head\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        newnode = Node(insertVal)\n",
    "        if not head: \n",
    "            newnode.next = newnode\n",
    "            return newnode\n",
    "        if head.next == head:\n",
    "            head.next = newnode\n",
    "            newnode.next = head\n",
    "            return head\n",
    "        pre = head\n",
    "        \n",
    "        while pre.next  and pre.next != head:\n",
    "            if pre.next.val >= pre.val:\n",
    "                pre = pre.next\n",
    "            else:\n",
    "                break   \n",
    "        if pre.val <= insertVal:\n",
    "            newnode.next = pre.next\n",
    "            pre.next = newnode\n",
    "        else:\n",
    "            while pre.next and pre.next.val<insertVal:\n",
    "                pre = pre.next\n",
    "            newnode.next = pre.next\n",
    "            pre.next = newnode\n",
    "\n",
    "        return head\n",
    "\n",
    "# 作者：Efred\n",
    "# 链接：https://leetcode.cn/problems/insert-into-a-sorted-circular-linked-list/solutions/2342163/yi-bian-bian-li-xun-huan-lian-biao-cha-z-b2m2/\n",
    "# 来源：力扣（LeetCode）\n",
    "# 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            head = Node(insertVal)\n",
    "            head.next = head\n",
    "            return head\n",
    "        pre = head\n",
    "        cur = head.next\n",
    "\n",
    "        while cur != head:\n",
    "            if pre.val > cur.val:\n",
    "                if insertVal >= pre.val or insertVal <= cur.val:\n",
    "                    node = Node(insertVal, cur)\n",
    "                    pre.next = node\n",
    "                    return head\n",
    "            if pre.val <= insertVal <= cur.val:\n",
    "                node = Node(insertVal, cur)\n",
    "                pre.next = node\n",
    "                return head\n",
    "            pre = cur\n",
    "            cur = cur.next\n",
    "        \n",
    "        node = Node(insertVal, cur)\n",
    "        pre.next = node\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        \n",
    "        new_node = Node(insertVal)\n",
    "\n",
    "        if not head: # 空链表，返回新建节点，注意新节点要指向自己\n",
    "            new_node.next = new_node\n",
    "            return new_node\n",
    "\n",
    "        if not head.next: # 单值链表，把新节点加入，互相指向\n",
    "            new_node.next = head\n",
    "            head.next = new_node\n",
    "            return head\n",
    "        \n",
    "        p, max_p = head, head # max_p是值最大的那个节点\n",
    "        while True:\n",
    "            if p.val >= max_p.val:\n",
    "                max_p = p\n",
    "            \n",
    "            if p.val <= insertVal <= p.next.val:\n",
    "                break\n",
    "            \n",
    "            p = p.next\n",
    "            if p == head:\n",
    "                break\n",
    "        \n",
    "        if p != head: # 找到一个插入点\n",
    "            tmp = p.next\n",
    "            p.next = new_node\n",
    "            new_node.next = tmp\n",
    "        else:\n",
    "            # 把新节点插入最大最小值之间\n",
    "            tmp = max_p.next\n",
    "            max_p.next = new_node\n",
    "            new_node.next = tmp\n",
    "\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            new_node = Node(insertVal)\n",
    "            new_node.next = new_node\n",
    "            return new_node\n",
    "        pre, cur = head, head.next\n",
    "        toInsert = False\n",
    "        while cur and cur.next:\n",
    "            if pre.val <= insertVal <= cur.val:\n",
    "                toInsert = True\n",
    "            if pre.val > cur.val:\n",
    "                if insertVal >= pre.val or insertVal <= cur.val:\n",
    "                    toInsert = True\n",
    "            if cur == head:\n",
    "                toInsert = True\n",
    "            if toInsert:\n",
    "                pre.next = Node(insertVal, cur)\n",
    "                return head\n",
    "            pre, cur = cur, cur.next\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head is None:\n",
    "            n = Node(insertVal)\n",
    "            n.next = n\n",
    "            return n\n",
    "\n",
    "        target_node = head\n",
    "        cur = head\n",
    "        while True:\n",
    "            if cur.val <= insertVal <= cur.next.val:\n",
    "                target_node = cur\n",
    "                break\n",
    "            if cur.val >= target_node.val:\n",
    "                target_node = cur\n",
    "            cur = cur.next\n",
    "            if cur == head:\n",
    "                break\n",
    "\n",
    "        n = Node(insertVal, target_node.next)\n",
    "        target_node.next = n\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        \n",
    "        if not head:\n",
    "            head = Node(insertVal)\n",
    "            head.next = head\n",
    "            return head\n",
    "        elif head.next == head:\n",
    "            head.next = Node(insertVal)\n",
    "            head.next.next = head\n",
    "            return head\n",
    "        else:\n",
    "            root = Node(-1)\n",
    "            root.next = head\n",
    "\n",
    "            fast, slow = head, root\n",
    "            \n",
    "            while True:\n",
    "                fast = fast.next    \n",
    "                slow = slow.next\n",
    "                if fast.val >= insertVal >= slow.val:\n",
    "                    slow.next = Node(insertVal)\n",
    "                    slow.next.next = fast\n",
    "                    break\n",
    "                elif fast.val < slow.val and insertVal < fast.val:\n",
    "                    slow.next = Node(insertVal)\n",
    "                    slow.next.next = fast\n",
    "                    break\n",
    "                elif fast.val < slow.val and insertVal > slow.val:\n",
    "                    slow.next = Node(insertVal)\n",
    "                    slow.next.next = fast\n",
    "                    break\n",
    "                elif fast == head:\n",
    "                    slow.next = Node(insertVal)\n",
    "                    slow.next.next = fast\n",
    "                    break\n",
    "\n",
    "            return root.next\n",
    "            \n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            head = Node(insertVal)\n",
    "            head.next = head\n",
    "            return head\n",
    "        pre = head\n",
    "        cur = head.next\n",
    "        while cur != head:\n",
    "            if pre.val <= insertVal <= cur.val or pre.val > cur.val and (insertVal < cur.val or insertVal > pre.val):\n",
    "                break\n",
    "            pre = cur\n",
    "            cur = cur.next\n",
    "        node = Node(insertVal)\n",
    "        pre.next = node\n",
    "        node.next = cur\n",
    "        return head\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(insertVal)\n",
    "        if not head:\n",
    "            node.next = node\n",
    "            return node\n",
    "        \n",
    "        ptr = head.next\n",
    "\n",
    "        # ptr.val <= ptr.next.val and ptr.val <= intervalVal and insertVal <= ptr.next.val\n",
    "        # ptr.val >= ptr.next.val (max -> min) and (ptr.val <= intervalVal or interval <= ptr.next.val)\n",
    "\n",
    "        while True:\n",
    "            if ptr.val <= ptr.next.val:\n",
    "                if ptr.val <= insertVal and insertVal <= ptr.next.val:\n",
    "                    break\n",
    "            elif ptr.val <= insertVal or insertVal <= ptr.next.val:\n",
    "                    break\n",
    "\n",
    "            if ptr == head:\n",
    "                break\n",
    "            else:\n",
    "                 ptr = ptr.next\n",
    "        \n",
    "        \n",
    "        node.next = ptr.next\n",
    "        ptr.next = node\n",
    "\n",
    "        return head\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            ans = Node(insertVal)\n",
    "            ans.next = ans\n",
    "            return ans\n",
    "\n",
    "        cur = head\n",
    "        lower = upper = head\n",
    "        while cur:\n",
    "            if cur.val < lower.val:\n",
    "                lower = cur\n",
    "            if cur.val > upper.val:\n",
    "                upper = cur\n",
    "            cur = cur.next\n",
    "            if cur == head:\n",
    "                break\n",
    "\n",
    "        if insertVal < lower.val or insertVal > upper.val:\n",
    "            cur = head\n",
    "            while cur:\n",
    "                if cur.val == upper.val and cur.next.val == lower.val:\n",
    "                    node = Node(insertVal)\n",
    "                    tmp = cur.next\n",
    "                    cur.next = node\n",
    "                    cur.next.next = tmp\n",
    "                    return head\n",
    "                cur = cur.next\n",
    "\n",
    "        cur = head\n",
    "        while cur:\n",
    "            if cur.val <= insertVal <= cur.next.val:\n",
    "                node = Node(insertVal)\n",
    "                tmp = cur.next\n",
    "                cur.next = node\n",
    "                cur.next.next = tmp\n",
    "                return head\n",
    "            cur = cur.next"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "# class Solution:\n",
    "#     def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "#         mark_head = head\n",
    "#         curr = head\n",
    "#         pre = head\n",
    "#         while curr and insertVal < curr.val:\n",
    "#             print(f'pre {curr.val}')\n",
    "#             pre = curr\n",
    "#             curr = curr.next\n",
    "#             print(f'aft {curr.val}')\n",
    "#         new = Node(insertVal)\n",
    "#         print(curr)\n",
    "#         temp = curr.next\n",
    "#         curr.next = new\n",
    "#         new.next = temp\n",
    "        \n",
    "#         return mark_head\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        newnode = Node(insertVal)\n",
    "        if not head: \n",
    "            newnode.next = newnode\n",
    "            return newnode\n",
    "        if head.next == head:\n",
    "            head.next = newnode\n",
    "            newnode.next = head\n",
    "            return head\n",
    "        pre = head\n",
    "        \n",
    "        while pre.next and pre.next != head:\n",
    "            if pre.next.val >= pre.val:\n",
    "                pre = pre.next\n",
    "            else:\n",
    "                break   \n",
    "        if pre.val <= insertVal:\n",
    "            newnode.next = pre.next\n",
    "            pre.next = newnode\n",
    "        else:\n",
    "            while pre.next and pre.next.val<insertVal:\n",
    "                pre = pre.next\n",
    "            newnode.next = pre.next\n",
    "            pre.next = newnode\n",
    "\n",
    "        return head\n",
    "\n",
    "# 作者：Efred\n",
    "# 链接：https://leetcode.cn/problems/insert-into-a-sorted-circular-linked-list/solutions/2342163/yi-bian-bian-li-xun-huan-lian-biao-cha-z-b2m2/\n",
    "# 来源：力扣（LeetCode）\n",
    "# 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        \n",
    "        if head == None:\n",
    "            newNode = Node(insertVal, None)\n",
    "            newNode.next = newNode\n",
    "            return newNode\n",
    " \n",
    "        prev, curr = head, head.next\n",
    "        toInsert = False\n",
    "\n",
    "        while True:\n",
    "            \n",
    "            if prev.val <= insertVal <= curr.val:\n",
    "                # Case #1.\n",
    "                toInsert = True\n",
    "            elif prev.val > curr.val:\n",
    "                # Case #2. 我们定位尾部元素‘prev’的位置指向尾部\n",
    "                # 例. 最大的元素！\n",
    "                if insertVal >= prev.val or insertVal <= curr.val:\n",
    "                    toInsert = True\n",
    "\n",
    "            if toInsert:\n",
    "                prev.next = Node(insertVal, curr)\n",
    "                # 任务完成\n",
    "                return head\n",
    "\n",
    "            prev, curr = curr, curr.next\n",
    "            # 循环条件\n",
    "            if prev == head:\n",
    "                break\n",
    "        # Case #3.\n",
    "        # 未在循环中插入节点\n",
    "        prev.next = Node(insertVal, curr)\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head == None:\n",
    "            h = Node(insertVal, None)\n",
    "            h.next = h \n",
    "            return h \n",
    "        if head.next == head:\n",
    "            head.next = Node(insertVal, head)\n",
    "            return head \n",
    "        \n",
    "        pre = head \n",
    "        p = pre.next\n",
    "        while True:\n",
    "            if pre.val <= insertVal <= p.val:\n",
    "                pre.next = Node(insertVal, p)\n",
    "                return head \n",
    "            elif pre.val > p.val:\n",
    "                if (pre.val <= insertVal and insertVal >= p.val) or (pre.val >= insertVal and insertVal <= p.val):\n",
    "                    pre.next = Node(insertVal, p)\n",
    "                    return head \n",
    "            pre = p \n",
    "            p = p.next\n",
    "            if pre == head:\n",
    "                break \n",
    "        pre.next = Node(insertVal, p)\n",
    "        return head \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            new_node = Node(insertVal)\n",
    "            new_node.next = new_node\n",
    "            return new_node\n",
    "        pre, cur = head, head.next\n",
    "        toInsert = False\n",
    "        while cur: #and cur.next:\n",
    "            if pre.val <= insertVal <= cur.val:\n",
    "                toInsert = True\n",
    "            if pre.val > cur.val:\n",
    "                if insertVal >= pre.val or insertVal <= cur.val:\n",
    "                    toInsert = True\n",
    "            if cur == head:\n",
    "                toInsert = True\n",
    "            if toInsert:\n",
    "                pre.next = Node(insertVal, cur)\n",
    "                return head\n",
    "            pre, cur = cur, cur.next\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        DO_WHILE_FLAG = True\n",
    "        cur = head\n",
    "\n",
    "        if not head:\n",
    "            insertNode = Node(insertVal, None)\n",
    "            insertNode.next = insertNode\n",
    "            return insertNode\n",
    "\n",
    "        while cur != head or DO_WHILE_FLAG:\n",
    "            DO_WHILE_FLAG = False\n",
    "            if cur.val <= insertVal and insertVal <= cur.next.val:\n",
    "                break\n",
    "            if cur.val > cur.next.val and (insertVal > cur.val or insertVal < cur.next.val):\n",
    "                break\n",
    "            cur = cur.next\n",
    "\n",
    "        insertNode = Node(insertVal, cur.next)\n",
    "        cur.next = insertNode\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            node = Node(insertVal)\n",
    "            node.next = node\n",
    "            return node\n",
    "        pre = head\n",
    "        cur = head.next\n",
    "        while cur != head:\n",
    "            if pre.val <= insertVal <= cur.val or (pre.val > cur.val and (insertVal >= pre.val or insertVal <= cur.val)):\n",
    "                node = Node(insertVal)\n",
    "                node.next = pre.next\n",
    "                pre.next = node\n",
    "                return head\n",
    "            pre = cur\n",
    "            cur = cur.next\n",
    "        node = Node(insertVal)\n",
    "        node.next = pre.next\n",
    "        pre.next = node\n",
    "        return head "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            head = Node(insertVal)\n",
    "            head.next = head\n",
    "            return head\n",
    "        \n",
    "        if head.next == head:\n",
    "            head.next = Node(insertVal, head)\n",
    "            return head\n",
    "        \n",
    "        toInsert = False\n",
    "        cur = head\n",
    "        while True:\n",
    "            if cur.val <= insertVal <= cur.next.val:\n",
    "                toInsert = True\n",
    "            if cur.next.val < cur.val <= insertVal or insertVal <= cur.next.val < cur.val:\n",
    "                toInsert = True\n",
    "            if cur.next == head:\n",
    "                toInsert = True\n",
    "                \n",
    "            if toInsert:\n",
    "                newnode = Node(insertVal, cur.next)\n",
    "                cur.next = newnode\n",
    "                return head\n",
    "            \n",
    "            cur = cur.next     "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            insert_node = Node(val=insertVal)\n",
    "            insert_node.next = insert_node\n",
    "            return insert_node\n",
    "        \n",
    "        prev, curr = head, head.next\n",
    "\n",
    "        is_inserted = False\n",
    "\n",
    "        while True:\n",
    "            if prev.val <= insertVal and insertVal <= curr.val:\n",
    "                is_inserted = True\n",
    "            elif prev.val > curr.val:\n",
    "                if insertVal >= prev.val or insertVal <= curr.val:\n",
    "                    is_inserted = True\n",
    "            \n",
    "            if is_inserted:\n",
    "                prev.next = Node(val=insertVal, next=curr)\n",
    "                return head\n",
    "            \n",
    "            prev, curr = curr, curr.next\n",
    "\n",
    "            if prev == head:\n",
    "                break\n",
    "        \n",
    "        prev.next = Node(val=insertVal, next=curr)\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            node = Node(insertVal)\n",
    "            node.next = node\n",
    "            return node\n",
    "        pre = head\n",
    "        cur = head.next\n",
    "        while cur != head:\n",
    "            if pre.val <= insertVal <= cur.val or \\\n",
    "            (pre.val > cur.val and (insertVal >= pre.val or insertVal <= cur.val)):\n",
    "                node = Node(insertVal)\n",
    "                node.next = pre.next\n",
    "                pre.next = node\n",
    "                return head\n",
    "            pre = cur\n",
    "            cur = cur.next\n",
    "        node = Node(insertVal)\n",
    "        node.next = pre.next\n",
    "        pre.next = node\n",
    "        return head "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head==None:\n",
    "            newNode=Node(insertVal,None)\n",
    "            newNode.next=newNode\n",
    "            return newNode\n",
    "        prev,cur=head,head.next\n",
    "        toInsert=False\n",
    "        while True:\n",
    "            if prev.val<=insertVal<=cur.val:\n",
    "                toInsert=True\n",
    "            elif prev.val>cur.val:\n",
    "                if insertVal>=prev.val or insertVal<=cur.val:\n",
    "                    toInsert=True\n",
    "            if toInsert:\n",
    "                prev.next=Node(insertVal,cur)\n",
    "                return head\n",
    "            \n",
    "            prev,cur=cur,cur.next\n",
    "            if prev==head:\n",
    "                break\n",
    "        prev.next=Node(insertVal,cur)\n",
    "        return head\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            head = Node(insertVal)\n",
    "            head.next = head\n",
    "            return head\n",
    "        pre = head\n",
    "        cur = head.next\n",
    "        while cur != head:\n",
    "            if pre.val <= insertVal <= cur.val or pre.val > cur.val and (insertVal < cur.val or insertVal > pre.val):\n",
    "                break\n",
    "            pre = cur\n",
    "            cur = cur.next\n",
    "        node = Node(insertVal)\n",
    "        pre.next = node\n",
    "        node.next = cur\n",
    "        return head\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            res = Node(insertVal,Node)\n",
    "            res.next = res\n",
    "            return res\n",
    "        prev,cur = head,head.next\n",
    "        insertNow = False\n",
    "        while True:\n",
    "            if prev.val<=insertVal<=cur.val:\n",
    "                insertNow = True\n",
    "            elif prev.val>cur.val and (prev.val<=insertVal or cur.val>=insertVal):\n",
    "                insertNow = True\n",
    "            if insertNow:\n",
    "                prev.next = Node(insertVal,cur)\n",
    "                return head \n",
    "            prev,cur = prev.next,cur.next\n",
    "            if prev==head: break\n",
    "        head.next = Node(insertVal,head.next)\n",
    "        return head\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        ins = Node(insertVal)\n",
    "        if not head:\n",
    "            head = ins\n",
    "            head.next = head\n",
    "            return head\n",
    "        pre, cur = head, head.next\n",
    "        toinsert = False\n",
    "        while True:\n",
    "            if pre.val <= insertVal <= cur.val:\n",
    "                toinsert = True\n",
    "            elif pre.val > cur.val:\n",
    "                if insertVal >= pre.val or insertVal <= cur.val:\n",
    "\n",
    "                    toinsert = True\n",
    "            \n",
    "            if toinsert:\n",
    "                pre.next = Node(insertVal, cur)\n",
    "                return head\n",
    "            pre, cur = cur, cur.next\n",
    "\n",
    "            if pre == head:\n",
    "                break\n",
    "\n",
    "        \n",
    "        pre.next = Node(insertVal, cur)\n",
    "        return head\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head: \n",
    "            head = Node(insertVal)\n",
    "            head.next = head\n",
    "            return head\n",
    "        pre = head\n",
    "        cur = head.next\n",
    "        insert = False\n",
    "        while True:\n",
    "            if pre.val <= insertVal <= cur.val:\n",
    "                insert = True\n",
    "            elif pre.val > cur.val:\n",
    "                if insertVal >= pre.val or insertVal <= cur.val:\n",
    "                    insert = True\n",
    "            if insert:\n",
    "                break\n",
    "            pre = cur\n",
    "            cur = cur.next\n",
    "\n",
    "            if pre == head:\n",
    "                break\n",
    "        pre.next = Node(insertVal, cur)\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head is None:\n",
    "            new_node = Node(insertVal)\n",
    "            new_node.next = new_node\n",
    "            return new_node\n",
    "        pre, cur = head, head.next\n",
    "        toInsert = False\n",
    "        while cur and cur.next:\n",
    "            if pre.val <= insertVal <= cur.val:\n",
    "                toInsert = True\n",
    "            if pre.val > cur.val:\n",
    "                if insertVal >= pre.val or insertVal <= cur.val:\n",
    "                    toInsert = True\n",
    "  \n",
    "            # loop condition\n",
    "            if cur == head: # Case #3.所以数字都一样\n",
    "                toInsert = True\n",
    "\n",
    "            if toInsert:\n",
    "                pre.next = Node(insertVal, cur) # next is curr\n",
    "                # mission accomplished\n",
    "                return head\n",
    "\n",
    "            pre, cur = cur, cur.next\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        iv = Node(insertVal)\n",
    "        if not head:\n",
    "            iv.next = iv\n",
    "            return iv\n",
    "        elif head.next == head: # only one\n",
    "            head.next = iv\n",
    "            iv.next = head\n",
    "        else:\n",
    "            it = head\n",
    "            r = False\n",
    "            while True:\n",
    "                if (it.val <= iv.val <=it.next.val) or \\\n",
    "                    ((it.next.val < it.val or (it.next.val == it.val and r)) \\\n",
    "                    and (iv.val <= it.next.val or it.val <= iv.val)):\n",
    "                    iv.next = it.next\n",
    "                    it.next = iv\n",
    "                    break\n",
    "                else:\n",
    "                    it = it.next\n",
    "                if head == it.next:\n",
    "                    r = True\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head is None:\n",
    "            n = Node(insertVal)\n",
    "            n.next = n\n",
    "            return n\n",
    "\n",
    "        cur = head.next\n",
    "        while cur != head:\n",
    "            if (cur.val <= insertVal <= cur.next.val) or (cur.val > cur.next.val and (insertVal >= cur.val or insertVal <= cur.next.val)):\n",
    "                break\n",
    "            cur = cur.next\n",
    "\n",
    "        cur.next = Node(insertVal, cur.next)\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        schPoint = head\n",
    "        if not schPoint:\n",
    "            head = Node(insertVal, None)\n",
    "            head.next = head\n",
    "            return head\n",
    "        length = 1\n",
    "        schPoint = schPoint.next\n",
    "        newNode = Node(insertVal,None)\n",
    "        while schPoint != head:\n",
    "            length += 1\n",
    "            schPoint = schPoint.next\n",
    "        if length == 1:\n",
    "            newNode.next = schPoint.next\n",
    "            schPoint.next = newNode\n",
    "            return head\n",
    "        schPoint = head\n",
    "        for i in range(length):\n",
    "            # print(schPoint.val)\n",
    "            if schPoint.val <= insertVal < schPoint.next.val:\n",
    "                newNode.next = schPoint.next\n",
    "                schPoint.next = newNode\n",
    "                return head\n",
    "            if schPoint.val > schPoint.next.val and (schPoint.val <= insertVal or schPoint.next.val >= insertVal):\n",
    "                newNode.next = schPoint.next\n",
    "                schPoint.next = newNode\n",
    "                return head\n",
    "            schPoint = schPoint.next\n",
    "        # print(1)\n",
    "        newNode.next = schPoint.next\n",
    "        schPoint.next = newNode\n",
    "        return head\n",
    "        \n",
    "        \n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "# class Solution:\n",
    "#     def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "#         mark_head = head\n",
    "#         cur = head\n",
    "#         pre = head\n",
    "#         while cur and insertVal < cur.val:\n",
    "#             print(f'pre {cur.val}')\n",
    "#             pre = cur\n",
    "#             cur = cur.next\n",
    "#             print(f'aft {cur.val}')\n",
    "#         new = Node(insertVal)\n",
    "#         print(cur)\n",
    "#         temp = cur.next\n",
    "#         cur.next = new\n",
    "#         new.next = temp\n",
    "        \n",
    "#         return mark_head\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Node', insertVal: int) -> 'Node':\n",
    "        node = Node(insertVal)\n",
    "        if not head:\n",
    "            node.next = node\n",
    "            return node\n",
    "        if head.next == head:\n",
    "            head.next = node\n",
    "            node.next = head\n",
    "            return head\n",
    "        curr,next = head, head.next\n",
    "        #一边遍历找插入位置\n",
    "        while next != head:\n",
    "            if curr.val <= insertVal <= next.val:\n",
    "                break\n",
    "            if curr.val > next.val:\n",
    "                if insertVal > curr.val or insertVal < next.val:\n",
    "                    break\n",
    "            curr, next = curr.next, next.next\n",
    "        curr.next, node.next = node, next\n",
    "        return head\n",
    "\n",
    "# 作者：Efred\n",
    "# 链接：https://leetcode.cn/problems/insert-into-a-sorted-circular-linked-list/solutions/2342163/yi-bian-bian-li-xun-huan-lian-biao-cha-z-b2m2/\n",
    "# 来源：力扣（LeetCode）\n",
    "# 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(insertVal)\n",
    "        # 特殊情况\n",
    "        if head is None:\n",
    "            node.next = node\n",
    "            return node\n",
    "        if head.next == head:\n",
    "            head.next = node\n",
    "            node.next = head\n",
    "            return head\n",
    "        curr = head\n",
    "        next = head.next\n",
    "        while next != head:\n",
    "            if curr.val <= insertVal <= next.val:\n",
    "                break\n",
    "            if curr.val > next.val:\n",
    "                if insertVal > curr.val or insertVal < next.val:\n",
    "                    break\n",
    "            curr = curr.next\n",
    "            next = next.next\n",
    "        curr.next = node\n",
    "        node.next = next\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(insertVal)\n",
    "        if not head:\n",
    "            node.next = node\n",
    "            return node\n",
    "\n",
    "        cur = head\n",
    "        while True:\n",
    "            \n",
    "            if (# 大于小的小于大的\n",
    "                cur.val <= insertVal\n",
    "                and insertVal <= cur.next.val\n",
    "                # 大于大的，小于小的，在尾和头分别插入，因为and前半句\n",
    "                or cur.val > cur.next.val and (insertVal <= cur.next.val \n",
    "                or insertVal >= cur.val)\n",
    "                #循环链表中每个值相等，注意由于while true循环，这里起到了验证每一个节点的作用\n",
    "                or cur.next == head\n",
    "            ):\n",
    "            \n",
    "                node.next = cur.next\n",
    "                cur.next = node\n",
    "                break\n",
    "\n",
    "            cur = cur.next\n",
    "        return head\n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            node = Node(insertVal)\n",
    "            node.next = node\n",
    "            return node\n",
    "        pre = head\n",
    "        cur = head.next\n",
    "        flag = False\n",
    "        while True:\n",
    "            if pre.val <= insertVal <= cur.val:\n",
    "                flag = True\n",
    "            elif pre.val > cur.val:\n",
    "                if insertVal >= pre.val or insertVal <= cur.val:\n",
    "                    flag = True\n",
    "            if flag:\n",
    "                pre.next = Node(insertVal, cur)\n",
    "                return head\n",
    "            pre = pre.next\n",
    "            cur = cur.next\n",
    "            if pre == head:\n",
    "                break\n",
    "\n",
    "        pre.next = Node(insertVal, cur);\n",
    "        return head "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            new_node = Node(insertVal)\n",
    "            new_node.next = new_node\n",
    "            return new_node\n",
    "        pre, cur = head, head.next\n",
    "        find = False\n",
    "        while cur:\n",
    "            if pre.val <= insertVal <= cur.val:\n",
    "                find = True\n",
    "            if pre.val > cur.val:\n",
    "                # >= <= not > <\n",
    "                if insertVal >= pre.val or insertVal <= cur.val: \n",
    "                    find = True\n",
    "            if cur== head: # important # cur not cur.val\n",
    "                find = True\n",
    "            if find:\n",
    "                pre.next = Node(insertVal, cur)\n",
    "                return head # this line\n",
    "            pre, cur = cur, cur.next # this line\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            result = Node(insertVal)\n",
    "            result.next = result\n",
    "            return result\n",
    "        cur, nxt = head, head.next\n",
    "        while nxt != head:\n",
    "            if cur.val <= insertVal <= nxt.val: break\n",
    "            if nxt.val < cur.val and (insertVal >= cur.val or insertVal <= nxt.val): break\n",
    "            cur = nxt\n",
    "            nxt = nxt.next\n",
    "        new_node = Node(insertVal, nxt)\n",
    "        cur.next = new_node\n",
    "        return head\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head is None:\n",
    "            n = Node(insertVal)\n",
    "            n.next = n\n",
    "            return n\n",
    "\n",
    "        cur = head.next\n",
    "        while cur != head:\n",
    "            # 几个可能性：找到上下界、是最大值或者最小值\n",
    "            if (cur.val <= insertVal <= cur.next.val) or (cur.val > cur.next.val and (insertVal >= cur.val or insertVal <= cur.next.val)):\n",
    "                break\n",
    "            cur = cur.next\n",
    "            # 或者循环一遍之后都不满足，那就只剩最后一个合适的位置：head 后面\n",
    "\n",
    "        cur.next = Node(insertVal, cur.next)\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head is None:\n",
    "            n = Node(insertVal)\n",
    "            n.next = n\n",
    "            return n\n",
    "\n",
    "        max_node = head\n",
    "        cur = head.next\n",
    "        while cur != head and cur.val >= max_node.val:\n",
    "            max_node =cur\n",
    "            cur = cur.next\n",
    "\n",
    "        if insertVal >= max_node.val:\n",
    "            n = Node(insertVal, max_node.next)\n",
    "            max_node.next = n\n",
    "            return head\n",
    "\n",
    "        cur = max_node\n",
    "        while insertVal > cur.next.val:\n",
    "            cur = cur.next\n",
    "        n = Node(insertVal, cur.next)\n",
    "        cur.next = n\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(val=insertVal)\n",
    "        if head is None:\n",
    "            node.next = node\n",
    "            return node\n",
    "\n",
    "        if head == head.next:\n",
    "            head.next = node\n",
    "            node.next = head\n",
    "            return head\n",
    "\n",
    "        prev = head\n",
    "        cur = head.next \n",
    "        \n",
    "        while not (prev.val <= insertVal and insertVal <= cur.val):\n",
    "            if cur == head:\n",
    "                break\n",
    "            # if prev.val >= insertVal and cur.val <= prev.val and (cur.val >= insertVal or prev.val <):\n",
    "            #     break\n",
    "\n",
    "            if prev.val > cur.val and (prev.val < insertVal or cur.val > insertVal):\n",
    "                break\n",
    "\n",
    "            prev = prev.next\n",
    "            cur = cur.next\n",
    "\n",
    "        prev.next = node\n",
    "        node.next = cur\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        current=head\n",
    "        if not head:\n",
    "            cur=Node(insertVal)\n",
    "            cur.next=cur\n",
    "            return cur\n",
    "        if head.next==head:\n",
    "            tmp=Node(insertVal)\n",
    "            head.next=tmp \n",
    "            tmp.next=head\n",
    "            return head\n",
    "        cnt=0\n",
    "        while cnt==0 or current.next!=head.next:\n",
    "            a=current.val\n",
    "            b=current.next.val \n",
    "            if a<=insertVal<=b:\n",
    "                c=current.next\n",
    "                current.next=Node(insertVal)\n",
    "                current.next.next=c \n",
    "                return head \n",
    "            if a>b and insertVal<=b or a>b and insertVal>=a:\n",
    "                c=current.next\n",
    "                current.next=Node(insertVal)\n",
    "                current.next.next=c \n",
    "                return head\n",
    "            current=current.next\n",
    "            cnt+=1\n",
    "        tmp=head.next\n",
    "        head.next=Node(insertVal)\n",
    "        head.next.next=tmp\n",
    "        return head\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(insertVal)\n",
    "\n",
    "        if not head:\n",
    "            node.next = node\n",
    "            return node\n",
    "        if head.next == head:\n",
    "            node.next = head.next\n",
    "            head.next = node\n",
    "            return head\n",
    "        \n",
    "        cur, nxt = head, head.next\n",
    "        while nxt != head:\n",
    "            if cur.val <= insertVal and nxt.val >= insertVal:\n",
    "                break\n",
    "            \n",
    "            if cur.val > nxt.val:\n",
    "                if insertVal >= cur.val or nxt.val >= insertVal:\n",
    "                    break\n",
    "            cur = nxt\n",
    "            nxt = nxt.next\n",
    "        node.next = nxt\n",
    "        cur.next = node\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if head is None:\n",
    "            n = Node(insertVal)\n",
    "            n.next = n\n",
    "            return n\n",
    "\n",
    "        target_node = head\n",
    "        cur = head\n",
    "        while True:\n",
    "            if cur.val <= insertVal <= cur.next.val:\n",
    "                target_node = cur\n",
    "                break\n",
    "            if cur.val >= target_node.val:\n",
    "                target_node = cur\n",
    "            cur = cur.next\n",
    "            if cur == head:\n",
    "                break\n",
    "\n",
    "        n = Node(insertVal, target_node.next)\n",
    "        target_node.next = n\n",
    "        return head\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        node = Node(val=insertVal)\n",
    "        if not head:\n",
    "            node.next = node\n",
    "            return node\n",
    "        curr = head.next\n",
    "        while curr != head:\n",
    "            if curr.val <= insertVal <= curr.next.val:\n",
    "                break\n",
    "            if curr.val > curr.next.val:\n",
    "                if insertVal >= curr.val or insertVal <= curr.next.val:\n",
    "                    break\n",
    "            curr = curr.next\n",
    "        node.next = curr.next\n",
    "        curr.next = node\n",
    "        return head"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\"\"\"\n",
    "# Definition for a Node.\n",
    "class Node:\n",
    "    def __init__(self, val=None, next=None):\n",
    "        self.val = val\n",
    "        self.next = next\n",
    "\"\"\"\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        newNode = Node(insertVal)\n",
    "        if not head:\n",
    "            newNode.next = newNode\n",
    "            return newNode\n",
    "        elif head.next ==  head:\n",
    "            head.next = newNode\n",
    "            newNode.next = head\n",
    "            return head\n",
    "        else:\n",
    "            p = head\n",
    "            q = head.next\n",
    "            while (p.val <= q.val) :\n",
    "                p, q = q, q.next\n",
    "                if (q == head):\n",
    "                    break\n",
    "            minNode = q\n",
    "\n",
    "            if insertVal < minNode.val:\n",
    "                p.next = newNode\n",
    "                newNode.next = q\n",
    "            else:\n",
    "                while not( (p.val <= insertVal <= q.val) ):\n",
    "                    p, q = q, q.next\n",
    "                    if (q == minNode):\n",
    "                        break\n",
    "                p.next = newNode\n",
    "                newNode.next = q\n",
    "            \n",
    "\n",
    "                \n",
    "            \n",
    "            return head\n",
    "                \n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':\n",
    "        if not head:\n",
    "            current=Node(insertVal)\n",
    "            current.next=current\n",
    "            return current\n",
    "        current=head\n",
    "        current_next=head.next\n",
    "        mark=True\n",
    "        while True:\n",
    "            if current.val==current_next.val:\n",
    "                current=current.next\n",
    "                current_next=current_next.next\n",
    "                if current==head:\n",
    "                    new_node=Node(insertVal)\n",
    "                    current.next=new_node\n",
    "                    new_node.next=current_next\n",
    "                    return current\n",
    "            if mark:\n",
    "                if current.val<=insertVal<=current_next.val:\n",
    "                    new_node=Node(insertVal)\n",
    "                    current.next=new_node\n",
    "                    new_node.next=current_next\n",
    "                    mark=False\n",
    "            if current.val>current_next.val and mark and (insertVal<current_next.val or insertVal>current.val):\n",
    "                new_node=Node(insertVal)\n",
    "                current.next=new_node\n",
    "                new_node.next=current_next\n",
    "                mark=False        \n",
    "            current=current.next\n",
    "            current_next=current_next.next    \n",
    "            if current_next.val==head.val and mark:\n",
    "                new_node=Node(insertVal)\n",
    "                current.next=new_node\n",
    "                new_node.next=current_next\n",
    "                mark=False\n",
    "                return current.next.next\n",
    "            if current.val==head.val:\n",
    "                return current\n"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
